I tried to use a struct to eliminate the duplicate use of “GetPlayerViewPoint()”

Grabber.h

// SirCharles1990

#pragma once

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


struct FPlayerReach
{
	FVector PlayerLocation;
	FVector PlayerReach;
};

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class BUILDINGESCAPE_API UGrabber : public UActorComponent
{
	GENERATED_BODY()

public:	
	// Sets default values for this component's properties
	UGrabber();

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

protected:
	// Called when the game starts
	virtual void BeginPlay() override;

private:
	float Reach = 100.f;

	UPhysicsHandleComponent* PhysicsHandle = nullptr;
	UInputComponent* InputComponent = nullptr;

	void GetPhysicsHandle();
	void GetInputComponent();
	FHitResult GetFirstPhysicsBodyInReach(FPlayerReach&) const;
	FPlayerReach GetPlayerReach(FPlayerReach&) const;
	void Grab();
	void Release();
};

Grabber.cpp

// SirCharles1990


#include "Grabber.h"
#include "DrawDebugHelpers.h"
#include "Engine/World.h"
#include "GameFrameWork/Actor.h"
#include "GameFramework/PlayerController.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
	PrimaryComponentTick.bCanEverTick = true;
}

// Called when the game starts
void UGrabber::BeginPlay()
{
	Super::BeginPlay();

	GetPhysicsHandle();
	GetInputComponent();
}

// Called every frame
void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	
	if(PhysicsHandle->GrabbedComponent)
	{
		FPlayerReach PlayerReach;
		PhysicsHandle->SetTargetLocation(GetPlayerReach(PlayerReach).PlayerReach);
	}
}

void UGrabber::GetPhysicsHandle()
{
	PhysicsHandle = GetOwner()->FindComponentByClass<UPhysicsHandleComponent>();
}

void UGrabber::GetInputComponent()
{
	InputComponent = GetOwner()->FindComponentByClass<UInputComponent>();
	if(InputComponent)
	{
		InputComponent->BindAction("Grab", IE_Pressed, this, &UGrabber::Grab);
		InputComponent->BindAction("Release", IE_Released, this, &UGrabber::Release);
	}
}

// Calculate player, location and reach FVectors
FPlayerReach UGrabber::GetPlayerReach(FPlayerReach& PlayerReach) const
{
	FVector PlayerViewPointLocation;
	FRotator PlayerViewPointRotation;

	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(
		OUT PlayerViewPointLocation, 
		OUT PlayerViewPointRotation
	);

	PlayerReach.PlayerReach = PlayerViewPointLocation + PlayerViewPointRotation.Vector() * Reach;
	PlayerReach.PlayerLocation = PlayerViewPointLocation;

	return PlayerReach;
}

// Calculate which actor is within reach
FHitResult UGrabber::GetFirstPhysicsBodyInReach(FPlayerReach& PlayerReach) const
{
	FHitResult Hit;
	FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner());

	GetWorld()->LineTraceSingleByObjectType(
		OUT Hit,
		PlayerReach.PlayerLocation,
		PlayerReach.PlayerReach,
		FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
		TraceParams
	);

	AActor* ActorHit = Hit.GetActor();

	return Hit;
}

// Initialize PlayerReach struct and grab component if a component is within reach
void UGrabber::Grab()
{
	FPlayerReach PlayerReach = GetPlayerReach(PlayerReach);
	FHitResult HitResult = GetFirstPhysicsBodyInReach(PlayerReach);
	UPrimitiveComponent* ComponentToGrab = HitResult.GetComponent();

	if(ComponentToGrab)	
		PhysicsHandle->GrabComponentAtLocation(
			ComponentToGrab,
			NAME_None,
			GetPlayerReach(PlayerReach).PlayerReach
		);
}

// Release component if a component is being held
void UGrabber::Release()
{
	UPrimitiveComponent* HeldComponent = PhysicsHandle->GrabbedComponent;
	if(HeldComponent)
	{
		PhysicsHandle->ReleaseComponent();
	}
}

I’m open to constructive criticism, but it seems to work alright!

1 Like

This is definitely a nice approach Charles. Structs are handy for this sort of thing.

1 Like

Privacy & Terms