Description:
This is a small game I made while discovering Unreal Engine 4.0. The player starts in a dimly lit room with some weird looking furniture. He has to find out how to escape the room by interacting with objects and the room itself.
When the player stands on a pressure pad, that is highlighted by a spotlight, the door opens, but when he tries to go through the door, it closes before the player reaches it. To get through the door, the player has to put a certain weight on the pressure pad, by placing objects on it.
Started: 3 March 2018
Finished: 10 March 2018
Links:
Code:
This class is for picking up and dropping objects. The class detects if the player is in reach of a physics body and attaching it to the Physics Handle that is on the player, if he presses the shift key or right mouse button. If he releases the button, the object is dropped.
The class begins by searching for a Physics Handle and an Input Component on the player. The input component detects if a button is pressed or released and calls the function that is attached to it.
In the TickComponent, a line is traced from the player’s camera to see if there is something in front of him that can be attached to the Physics Handle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
#include "Grabber.h" #include "GameFramework/Actor.h" #include "Engine/World.h" #include "DrawDebugHelpers.h" #define OUT // Sets default values for this component's properties UGrabber::UGrabber() { // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features // off to improve performance if you don't need them. PrimaryComponentTick.bCanEverTick = true; } // Called when the game starts void UGrabber::BeginPlay() { Super::BeginPlay(); FindPhysicsHandleComponent(); SetupInputComponent(); } // Find attached Physics Handle component void UGrabber::FindPhysicsHandleComponent() { physicsHandle = GetOwner()->FindComponentByClass<UPhysicsHandleComponent>(); if (physicsHandle == nullptr) { UE_LOG(LogTemp, Error, TEXT("No physics handle has been found on %s!"), *GetOwner()->GetName()); } } // Setup attached Input Component void UGrabber::SetupInputComponent() { inputComponent = GetOwner()->FindComponentByClass<UInputComponent>(); if (inputComponent) { inputComponent->BindAction("Grab", IE_Pressed, this, &UGrabber::Grab); inputComponent->BindAction("Release", IE_Released, this, &UGrabber::Release); } else { UE_LOG(LogTemp, Error, TEXT("No input component has been foundon %s!"), *GetOwner()->GetName()); } } // Raycast and grab what's in reach void UGrabber::Grab() { FHitResult hitResult = GetFirstPhysicsBodyInReach(); UPrimitiveComponent* componentToGrab = hitResult.GetComponent(); AActor* actorHit = hitResult.GetActor(); /// If we hit something then attach a physics handle if (actorHit) { physicsHandle->GrabComponent( componentToGrab, NAME_None, componentToGrab->GetOwner()->GetActorLocation(), true ); } } void UGrabber::Release() { physicsHandle->ReleaseComponent(); } // Called every frame void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if (physicsHandle) { // If the physics handle is attached if (physicsHandle->GrabbedComponent) { // move the object that we're holding physicsHandle->SetTargetLocation(GetReachLineEnd()); } } } // Line trace and see if we reach any actors with physics body collision channel set const FHitResult UGrabber::GetFirstPhysicsBodyInReach() { /// Line-trace (aka Raycast) out to reach distance FHitResult hitResult; FCollisionQueryParams traceParameters(FName(TEXT("")), false, GetOwner()); GetWorld()->LineTraceSingleByObjectType( OUT hitResult, GetReachLineStart(), GetReachLineEnd(), FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody), traceParameters ); return hitResult; } // Returns current start of reach line FVector UGrabber::GetReachLineStart() { FVector playerViewPointLocation; FRotator playerViewPointRotation; GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(OUT playerViewPointLocation, OUT playerViewPointRotation); return playerViewPointLocation; } // Returns current end of reach line FVector UGrabber::GetReachLineEnd() { FVector playerViewPointLocation; FRotator playerViewPointRotation; GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(OUT playerViewPointLocation, OUT playerViewPointRotation); // Calculate the end of the line trace FVector lineTraceEnd = playerViewPointLocation + playerViewPointRotation.Vector() * reach; return lineTraceEnd; } |