Skip to content

Instantly share code, notes, and snippets.

Created August 8, 2017 15:16
Show Gist options
  • Save anonymous/29612d30689352f4c2e314a57259eeb2 to your computer and use it in GitHub Desktop.
Save anonymous/29612d30689352f4c2e314a57259eeb2 to your computer and use it in GitHub Desktop.
#include "Grabber.h"
#include "Engine/World.h"
#include "GameFramework/PlayerController.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.
bWantsBeginPlay = true;
PrimaryComponentTick.bCanEverTick = true;
}
// Called when the game starts
void UGrabber::BeginPlay()
{
Super::BeginPlay();
FindPhysicsHandleComponent();
SetupInputComponent();
}
/// Look for attached Physics Handle
void UGrabber::FindPhysicsHandleComponent()
{
/// Look for attached Input Component (only appears at run time)
PhysicsHandle = GetOwner()->FindComponentByClass<UPhysicsHandleComponent>();
if (PhysicsHandle == nullptr)
{
UE_LOG(LogTemp, Error, TEXT("%s missing physics handle component"), *GetOwner()->GetName())
}
}
/// Look for attached Input Component (only appears at run time)
void UGrabber::SetupInputComponent()
{
InputComponent = GetOwner()->FindComponentByClass<UInputComponent>();
if (InputComponent)
{
InputComponent->BindAction("Grab", IE_Pressed, this, &UGrabber::Grab);
InputComponent->BindAction("Grab", IE_Released, this, &UGrabber::Release);
}
else
{
UE_LOG(LogTemp, Error, TEXT("%s missing input component"), *GetOwner()->GetName())
}
}
// Called every frame
void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// if the phyiscs handle is attached
if (PhysicsHandle->GrabbedComponent)
{
// move the object that we're holding
PhysicsHandle->SetTargetLocation(GetReachLineEnd());
}
}
void UGrabber::Grab() {
/// LINE TRACE and see if we reach any actors with physics body collision channel set
auto HitResult = GetFirstPhysicsBodyInReach();
auto ComponentToGrab = HitResult.GetComponent(); //gets the mesh in our case
auto ActorHit = HitResult.GetActor();
/// If we hit something then attach a physics handle
if (ActorHit)
{
if (!PhysicsHandle) { return; }
PhysicsHandle->GrabComponentAtLocationWithRotation(
ComponentToGrab,
NAME_None, // no bones needed
ActorHit->GetActorLocation(),
ActorHit->GetActorRotation()
);
}
}
void UGrabber::Release()
{
UE_LOG(LogTemp, Warning, TEXT("Grab released"))
}
const FHitResult UGrabber::GetFirstPhysicsBodyInReach()
{
/// Line-trace (AKA ray-cast) 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;
}
FVector UGrabber::GetReachLineStart()
{
FVector PlayerViewPointLocation;
FRotator PlayerViewPointRotation;
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
OUT PlayerViewPointLocation,
OUT PlayerViewPointRotation
);
return PlayerViewPointLocation;
}
FVector UGrabber::GetReachLineEnd()
{
FVector PlayerViewPointLocation;
FRotator PlayerViewPointRotation;
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
OUT PlayerViewPointLocation,
OUT PlayerViewPointRotation
);
return PlayerViewPointLocation + PlayerViewPointRotation.Vector() * Reach;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment