Skip to content

Instantly share code, notes, and snippets.

@AaronGr
Created January 31, 2018 21:39
Show Gist options
  • Save AaronGr/35c99c0830c00fd5e4bd0fc7727f81f0 to your computer and use it in GitHub Desktop.
Save AaronGr/35c99c0830c00fd5e4bd0fc7727f81f0 to your computer and use it in GitHub Desktop.
My Refactored Code for Building Escape Grabber Class
// Copyright Aaron Gravelle
#include "Grabber.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();
SetupInputComponent();
SetupPhysicsHandleComponent();
}
// Called every frame
void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) {
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// If the physics handle is attached
if (PhysicsHandle->GrabbedComponent) {
// move the object that we're holding
PhysicsHandle->SetTargetLocation(GetEndOfReach());
}
}
void UGrabber::SetupInputComponent() {
InputComponent = GetOwner()->FindComponentByClass<UInputComponent>();
if (InputComponent) {
/// Bind the input action
InputComponent->BindAction("Grab", IE_Pressed, this, &UGrabber::Grab);
InputComponent->BindAction("Grab", IE_Released, this, &UGrabber::Release);
}
else {
UE_LOG(LogTemp, Error, TEXT("%s is missing InputComponent"), *(GetOwner()->GetName()));
}
}
void UGrabber::SetupPhysicsHandleComponent() {
/// Look for attached Physics Handle
PhysicsHandle = GetOwner()->FindComponentByClass<UPhysicsHandleComponent>();
if (!PhysicsHandle) {
UE_LOG(LogTemp, Error, TEXT("%s is missing PhysicsHandleComponent"), *(GetOwner()->GetName()));
}
}
void UGrabber::Grab() {
/// LINE TRACE and see if any actors with physics body collision channel set
auto ComponentToGrab = GetFirstPhysicsBodyInReach().GetComponent();
/// If we hit something then attach a physics handle
if (ComponentToGrab) {
// attach physics handle
PhysicsHandle->GrabComponentAtLocation(
ComponentToGrab,
NAME_None,
ComponentToGrab->GetOwner()->GetActorLocation()
);
}
}
void UGrabber::Release() {
PhysicsHandle->ReleaseComponent();
}
FHitResult UGrabber::GetFirstPhysicsBodyInReach() const {
/// Setup query parameter
FCollisionQueryParams TraceParameters(FName(TEXT("")), false, GetOwner());
/// Ray-cast to reach distance
FHitResult PhysicsBody;
GetWorld()->LineTraceSingleByObjectType(
OUT PhysicsBody,
GetOwner()->GetActorLocation(),
GetEndOfReach(),
FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
TraceParameters
);
return PhysicsBody;
}
FVector UGrabber::GetEndOfReach() const
{
PlayerPOV CurrentPOV = GetPlayerPOV();
return CurrentPOV.Location + (Reach * CurrentPOV.Rotation.Vector());
}
PlayerPOV UGrabber::GetPlayerPOV() const
{
PlayerPOV CurrentPOV;
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(OUT CurrentPOV.Location, OUT CurrentPOV.Rotation);
return CurrentPOV;
}
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "PhysicsEngine/PhysicsHandleComponent.h"
#include "DrawDebugHelpers.h"
#include "Engine/World.h"
#include "GameFramework/PlayerController.h"
#include "Grabber.generated.h"
struct PlayerPOV {
FVector Location;
FRotator Rotation;
};
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class BUILDINGESCAPE_API UGrabber : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UGrabber();
protected:
// Called when the game starts
virtual void BeginPlay() override;
// Find (assumed) attached input component
void SetupInputComponent();
// Setup (assumed) attached physics component
void SetupPhysicsHandleComponent();
// Return hit for first physics body in reach
FHitResult GetFirstPhysicsBodyInReach() const;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
private:
// How far ahead the player can reach in cm
UPROPERTY(EditAnywhere)
float Reach = 100.f;
UPhysicsHandleComponent* PhysicsHandle = nullptr;
UInputComponent* InputComponent = nullptr;
/// Ray-cast and grab what is in reach
void Grab();
void Release();
PlayerPOV GetPlayerPOV() const;
FVector GetEndOfReach() const;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment