Q. As you can see below my refactoring approach is a little bit different cuz I created too many functions. So will my refactoring approach is better than the refactoring approach we saw in the video in view of the latency of code execution.
Header:- (42 Lines of code)
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "PhysicsEngine/PhysicsHandleComponent.h"
#include "Grabber.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class ESCAPEBUILDING2_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* InputKeyBind = nullptr;
FHitResult Hit; //Hit Result
FVector TraceLineEnd;
//User Defined Functions
void CollisionWithObjects(FVector &PlayerViewPointLocation);
void FindPhysicsHandle();
void GrabbedObjectNewLocation();
void GrabObject();
void ReleaseObject();
void SetupInputComponent();
void ViewPointUpdater(FVector &PlayerViewPointLocation, FRotator &PlayerViewPointRotation);
CPP:- (112 lines of code)
// Fill out your copyright notice in the Description page of Project Settings.
#include "Grabber.h"
#include "DrawDebugHelpers.h"
#include "Engine/World.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
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
}
// Called when the game starts
void UGrabber::BeginPlay()
{
Super::BeginPlay();
FindPhysicsHandle();
SetupInputComponent();
}
// Called every frame
void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// Varaibles for trace line
FVector PlayerViewPointLocation;
FRotator PlayerViewPointRotation;
// Function for updating trace line's variables
ViewPointUpdater(OUT PlayerViewPointLocation,OUT PlayerViewPointRotation);
// Check if the pawn collides with any actor?
CollisionWithObjects(OUT PlayerViewPointLocation);
// Updates the location for grabbed object
if (PhysicsHandle->GrabbedComponent) //Unreal engine is crashing while executing this line
{
PhysicsHandle->SetTargetLocation(TraceLineEnd);
}
}
//User Defined Function
void UGrabber::GrabObject() // Function called for grabbing
{
UPrimitiveComponent *ComponentToGrab = Hit.GetComponent(); //Declares the componet of hit actor
if (Hit.GetActor()) //if traceline collide with any actor
{
PhysicsHandle->GrabComponentAtLocation //To grab component at following location
(
ComponentToGrab,
NAME_None,
TraceLineEnd
);
}
}
void UGrabber::ReleaseObject() // Function called for releasing grabbed object
{
PhysicsHandle->ReleaseComponent(); //Releases Grabbed Component
}
void UGrabber::FindPhysicsHandle() // Physics Handle Check
{
PhysicsHandle = GetOwner()->FindComponentByClass<UPhysicsHandleComponent>();
if (PhysicsHandle == nullptr)
{
UE_LOG(LogTemp, Error, TEXT("%s does not have PhysicsHandle set to it."), *GetOwner()->GetName()) // Physics Handle Not Found
}
}
void UGrabber::SetupInputComponent() // Input Bind Check & Input Bind Functions Calling
{
InputKeyBind = GetOwner()->FindComponentByClass<UInputComponent>();
if (InputKeyBind)
{
// Input Bind Found
InputKeyBind->BindAction("Grab", IE_Pressed, this, &UGrabber::GrabObject); // Function For Grabbing
InputKeyBind->BindAction("Grab", IE_Released, this, &UGrabber::ReleaseObject); // Function For Releasing Grabbed Object
}
}
void UGrabber::ViewPointUpdater(FVector &PlayerViewPointLocation, FRotator &PlayerViewPointRotation) // Updates Parameters as refrence
{
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(OUT PlayerViewPointLocation, OUT PlayerViewPointRotation); // Updates giver OUT parameters
TraceLineEnd = PlayerViewPointLocation + PlayerViewPointRotation.Vector() * Reach; // Updates TraceLineEnd
}
void UGrabber::CollisionWithObjects(FVector &PlayerViewPointLocation) // Trace a ray against the world using object types and return the first blocking hit
{
FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner()); // Additional parameters used for the trace
// Trace a ray against the world using object types and return the first blocking hit
GetWorld()->LineTraceSingleByObjectType( // Returns: TRUE if any hit is found
OUT Hit,
PlayerViewPointLocation,
TraceLineEnd,
FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
TraceParams);
}