My Refactored Code :)

.h

// StrivnX

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "PhysicsEngine/PhysicsHandleComponent.h"
#include "Grabber.generated.h"

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;

public:	
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

private:
	float Reach = 100.f;
	UPhysicsHandleComponent* PhysicsHandle = nullptr;
	UInputComponent* InputComponent = nullptr;

private:
	void Grab();
	void Release();
	void FindPhysicsHandle();
	void SetupInputComponent();
	FVector LineTraceEnd();
	FVector GetPlayerViewpointLocation();
	void PlayerViewpoint(FVector& GetPlayerViewpointLocationOUT, FRotator& PlayerViewpointRotationOUT);
	FHitResult GetFirstPhysicsBodyInReach();
};

.cpp

// StrivnX

#include "GameFramework/PlayerController.h"
#include "Engine/World.h"
#include "DrawDebugHelpers.h"
#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();
	//checking for physics handle component
	FindPhysicsHandle();
	SetupInputComponent();
}
void UGrabber::FindPhysicsHandle()
{
	PhysicsHandle = GetOwner()->FindComponentByClass<UPhysicsHandleComponent>();
	if (!PhysicsHandle)UE_LOG(LogTemp, Error, TEXT("PhysicsHandle are NOT Set!"));
}
void UGrabber::SetupInputComponent()
{
	InputComponent = GetOwner()->InputComponent;
	//bind delegate Functions To Actions defined in project setting 
	if (InputComponent)
	{
		InputComponent->BindAction("Grab", IE_Pressed, this, &UGrabber::Grab);
		InputComponent->BindAction("Grab", IE_Released, this, &UGrabber::Release);
	}
}
void UGrabber::Grab()
{
	//If we hit something then attach to the physics handle
	FHitResult HitResult = GetFirstPhysicsBodyInReach();
	UPrimitiveComponent* ComponentToGrab = HitResult.GetComponent();
	if (HitResult.GetActor())
	{
		HitResult.GetComponent()->GetRelativeRotation() = FRotator(0.f, 0.f, 0.f);
		//TODO attach to physics handle
		PhysicsHandle->GrabComponentAtLocationWithRotation(
			ComponentToGrab,
			NAME_None,
			HitResult.GetComponent()->GetRelativeLocation(),
			HitResult.GetComponent()->GetRelativeRotation()
		);
		PhysicsHandle->SetInterpolationSpeed(20.f);
	}
}
void UGrabber::Release()
{
	PhysicsHandle->ReleaseComponent();
}
// Called every frame
void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	//Get PlayerViewpoint
	FVector PlayerViewpointLocation;
	FRotator PlayerViewpointRotation;
	PlayerViewpoint(OUT PlayerViewpointLocation, OUT PlayerViewpointRotation);

	//Draw A Line for Showing the reach Of Ray-Cast 
	DrawDebugLine(
		GetWorld(), 
		GetPlayerViewpointLocation(), 
		LineTraceEnd(), 
		FColor(255, 0, 0), 
		false, 
		0.f, 
		0, 
		5.f);

	// If the "physicshandle" handle an object.
	if (PhysicsHandle->GetGrabbedComponent())
	{
		FRotator RPlayerAbove = PlayerViewpointRotation;
		RPlayerAbove = { PlayerViewpointRotation.Pitch + 90.f, PlayerViewpointRotation.Yaw, PlayerViewpointRotation.Roll };
		FVector LineTraceEndAbove = LineTraceEnd();
		LineTraceEndAbove = PlayerViewpointLocation + RPlayerAbove.Vector() * Reach;
		//Draw A Line for Showing where the object will be
		DrawDebugLine(GetWorld(), PlayerViewpointLocation, LineTraceEndAbove, FColor(0, 0, 0), false, 0.f, 0, 5.f);
		// Move the object we are holding.	
		PhysicsHandle->SetTargetLocationAndRotation(LineTraceEndAbove, PlayerViewpointRotation); // PlayerViewpointRotation is ObjectRotation
	}
}
FHitResult UGrabber::GetFirstPhysicsBodyInReach() 
{
	//Ray-Cast
	FHitResult HitResult;
	FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner());
	bool bHit = GetWorld()->LineTraceSingleByObjectType(
		OUT HitResult,
		GetPlayerViewpointLocation(),
		LineTraceEnd(),
		FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
		TraceParams
	);
	// See Waht it Hits
	if (bHit)
	{
		FString NameOfObject = HitResult.GetActor()->GetName(); 
		UE_LOG(LogTemp, Warning, TEXT("[FHitResult] Name Of Object: %s || GetCollisionProfileName %s"),*NameOfObject, *HitResult.GetComponent()->GetCollisionProfileName().ToString());
	}
	return HitResult;
}
FVector UGrabber::LineTraceEnd()
{
	FVector PlayerViewpointLocation;
	FRotator PlayerViewpointRotation;
	PlayerViewpoint(PlayerViewpointLocation, PlayerViewpointRotation);
	FVector PlayerForwardVector = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorForwardVector();//For Testing
	return PlayerViewpointLocation + PlayerViewpointRotation.Vector() * Reach;
}
void UGrabber::PlayerViewpoint(OUT FVector& PlayerViewpointLocationOUT, OUT FRotator& PlayerViewpointRotationOUT)
{
	// Get players viewpoint
	FVector PlayerViewpointLocation;
	FRotator PlayerViewpointRotation;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
		OUT PlayerViewpointLocation,
		OUT PlayerViewpointRotation);
	PlayerViewpointLocationOUT = PlayerViewpointLocation;
	PlayerViewpointRotationOUT = PlayerViewpointRotation;
}

FVector UGrabber::GetPlayerViewpointLocation()
{
	// Get players viewpoint
	FVector PlayerViewpointLocation;
	FRotator PlayerViewpointRotation;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
		OUT PlayerViewpointLocation, 
		OUT PlayerViewpointRotation);
	return PlayerViewpointLocation;
}
2 Likes

Fantastic. Refactoring is so important and can be involved when you have more code. It can also eliminate repetition and redundancy.

Thanks for sharing.

Privacy & Terms