After I did the doors blueprint section, I can’t pick up. I’ve added UE_LOG’s to try to find the area not working. It is logging “Grabber reporting to duty”, but it is not logging “Line trace hit” or “Location… Rotation”. Grabber is on Pawn. Don’t know if there’s a check box on the pawn or it’s collision that I need to check, or if it’s something in the code. Racking my beginner’s brain!
#include "Grabber.h"
#include "Runtime/Core/Public/Math/Vector.h"
#include "Runtime/Core/Public/Math/Rotator.h"
#include "GameFramework/Actor.h"
#include "GameFramework/Controller.h"
#include "GameFramework/PlayerController.h"
#include "Engine/World.h"
#include "DrawDebugHelpers.h"
#include "Runtime/Engine/Classes/Components/PrimitiveComponent.h"
#include <iostream>
#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();
UE_LOG(LogTemp, Warning, TEXT("Grabber reporting for duty"));
FindPhysicsHandleComponent();
SetupInputComponent();
}
// Called every frame
void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (!PhysicsHandle) { return; }
// if the physics handle is attached
if (PhysicsHandle->GrabbedComponent)
{
// move the object that we're holding
PhysicsHandle->SetTargetLocation(GetReachLineEnd());
}
}
//look for attached physics handle
// setup in grabber.h, defined PhysicsHandle variable as nullptr, here we define physicshandle
// looking above in tree, as owner, then looking back down the stack (findcomponentbyclass) to the
// added component as uphysics...
void UGrabber::FindPhysicsHandleComponent()
{
PhysicsHandle = GetOwner()->FindComponentByClass<UPhysicsHandleComponent>();
if (PhysicsHandle == nullptr)
{
UE_LOG(LogTemp, Error, TEXT("Add PhysicsHandle component to %s"), *GetOwner()->GetName());
}
}
// Look for attached Input Component (only appears at run time)
void UGrabber::SetupInputComponent()
{
if (!InputComponent) { return; }
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());
}
}
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
ComponentToGrab->GetOwner()->GetActorLocation(),
ComponentToGrab->GetOwner()->GetActorRotation()
);
ComponentToGrab->GetOwner()->SetActorRotation(FRotator(0.0f, 0.0f, 0.0f));
}
}
void UGrabber::Release()
{
if (!PhysicsHandle) { return; }
PhysicsHandle->ReleaseComponent();
}
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
);
// see what we hit
AActor* ActorHit = HitResult.GetActor();
if (ActorHit)
{
UE_LOG(LogTemp, Warning, TEXT("Line trace hit: %s"), *(ActorHit->GetName()));
}
return HitResult;
}
FVector UGrabber::GetReachLineStart()
{
FVector PlayerViewPointLocation;
FRotator PlayerViewPointRotation;
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
OUT PlayerViewPointLocation,
OUT PlayerViewPointRotation
);
UE_LOG(LogTemp, Warning, TEXT("Location: %s, Rotation: $s"),
*PlayerViewPointLocation.ToString(),
*PlayerViewPointRotation.ToString()
);
return PlayerViewPointLocation;
}
/// get player view point (end of reach line)
FVector UGrabber::GetReachLineEnd()
{
FVector PlayerViewPointLocation;
FRotator PlayerViewPointRotation;
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
OUT PlayerViewPointLocation,
OUT PlayerViewPointRotation
);
return PlayerViewPointLocation + (PlayerViewPointRotation.Vector() * Reach);
}