Download

Blueprint To C++, code behave wierd

Hello there!

I’m trying to convert a blueprint function into C++, a very simple grappling hook with the cable component class.
I’ve done the coding but when i test it, it’s behave wierd. When calling the LaunchCharacter() in code it’s always boosting me up with the given velocity while in the BP code its working fine.
And I can’t really get the end location of the cable component. Does anyone have any idea or had this problem before?

P.S.: Sorry because of my english

Code:
.h file



#pragma once
#include "GameFramework/Character.h"
#include "RandomStuffsCharacter.generated.h"

class UCableComponent;

UCLASS(config=Game)
class ARandomStuffsCharacter : public ACharacter
{
	GENERATED_BODY()
	//...
	
	//
	// Grappling Hook
	//

	UPROPERTY(BlueprintReadWrite, Category = HookCable)
	UCableComponent* HookCable;

	// Start the hook
	void StartHook();

	// Stop the hook
	void StopHook();

	// Move the rope to the hit location
	bool MoveRope();

	// Move the player to the rope
	void MovePlayer();

	// Are we hooked on something?
	bool bHooked;

	// Is the hooked finished moving to the hit location?
	bool bHookedFinished;

	float HookLength = 3000.0f;
	FVector HookLocation;

	virtual void Tick(float DeltaTime) override;
};


.cpp file



#include "RandomStuffs.h"
#include "CableComponent.h"
#include "RandomStuffsCharacter.h"

//////////////////////////////////////////////////////////////////////////
// ARandomStuffsCharacter

ARandomStuffsCharacter::ARandomStuffsCharacter()
{
	//...
	// Setup the cable for the hook visibility
	HookCable = CreateDefaultSubobject<UCableComponent>(TEXT("CableComponent"));
	HookCable->SetupAttachment(RootComponent);
	HookCable->CableLength = 0.0f;
	HookCable->CableWidth = 4.0f;
	HookCable->NumSegments = 10;
	HookCable->SolverIterations = 2;
	HookCable->SetVisibility(false);
	HookCable->EndLocation = FVector(0.0f, 0.0f, 0.0f);

	bHooked = false;
	bHookedFinished = false;

	HookLocation = FVector(0.0f, 0.0f, 0.0f);
}


void ARandomStuffsCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	//...
	PlayerInputComponent->BindAction("Hook", IE_Pressed, this, &ARandomStuffsCharacter::StartHook);
	PlayerInputComponent->BindAction("Hook", IE_Released, this, &ARandomStuffsCharacter::StopHook);
	//...
}

void ARandomStuffsCharacter::StartHook()
{
	FCollisionQueryParams TraceParams(TEXT(""), false, GetOwner());
	FHitResult HitResult;

	FVector StartLocation = HookCable->K2_GetComponentLocation();
	FVector EndLocation = (GetViewRotation().Vector() * HookLength) + StartLocation;

	bool bHitActor = GetWorld()->LineTraceSingleByChannel(
		HitResult,
		StartLocation,
		EndLocation,
		ECollisionChannel::ECC_MAX,
		TraceParams,
		FCollisionResponseParams::DefaultResponseParam
	);
	DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Red, true, -1.0f, 0, 1.5f);

	if (bHitActor)
	{
		bHooked = true;
		HookLocation = HitResult.Location;
	}
	else
	{
		StopHook();
	}
}

void ARandomStuffsCharacter::StopHook()
{
	bHooked = false;
	bHookedFinished = false;

	HookCable->SetVisibility(false);
	HookCable->GetComponentTransform().SetLocation(FVector(0, 0, 0));
}

bool ARandomStuffsCharacter::MoveRope()
{
	FVector HookWorldLoc = HookCable->K2_GetComponentLocation();
	HookCable->SetVisibility(true);

	FVector Distance = HookWorldLoc - HookLocation;
	if (Distance.Size() <= 100)
	{
		return true;
	}
	else
	{
		DrawDebugLine(GetWorld(), HookWorldLoc, HookLocation, FColor::Yellow, true, -1.0f, 0, 2.5f);
		HookCable->GetComponentTransform().SetLocation(FMath::VInterpTo(HookWorldLoc, HookLocation, GetWorld()->GetDeltaSeconds(), 35));
		return false;
	}
}

void ARandomStuffsCharacter::MovePlayer()
{
	FVector LaunchVel = ((HookLocation)) * ((GetWorld()->GetDeltaSeconds() * 250));
	LaunchCharacter(LaunchVel, true, true);
}

//...

void ARandomStuffsCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	UE_LOG(LogTemp, Warning, TEXT("Cable: %s"), *HookCable->K2_GetComponentLocation().ToString());
	UE_LOG(LogTemp, Warning, TEXT("Player: %s"), *GetTransform().GetLocation().ToString());

	if (bHooked)
	{
		if (bHookedFinished)
		{
			FVector NewLocation = FMath::VInterpConstantTo(
				HookCable->K2_GetComponentLocation(),
				HookLocation,
				GetWorld()->GetDeltaSeconds(),
				250
			);
			MovePlayer();
			HookCable->GetComponentTransform().SetLocation(NewLocation);
		}
		else
		{
			bHookedFinished = MoveRope();
		}
	}
}


Error:
C++ not working
91b2e345d6314875689a7f44b25fc8adaba8d25f.jpeg

Blueprint working fine
ScreenShot00001.jpg

Well, ECollisionChannel::ECC_MAX definitely seems wrong. What channel are you tracing on in blueprint?

I’m using WorldStatic and Dynamics as a Make Array in blueprint

Then you should be using LineTraceSingleByObjectType, not LineTraceSingleByChannel

Thanks, i changed the LineTrace, and I added some debug boxes and looked over the code again. The problem is that the FHitResult.ImpactPoint giving back wrong location. I don’t really know why is this not working.
The purple one should be the ImpactResult, the yellow one should be the current position of the hook component and the green point where you should grapple (the Impact Result).

ScreenShot00004.jpg



//////////////////////////////////////////////////////////////////////////
// ARandomStuffsCharacter

ARandomStuffsCharacter::ARandomStuffsCharacter()
{
	// Setup the cable for the hook visibility
	HookCable = CreateDefaultSubobject<UCableComponent>(TEXT("CableComponent"));
	HookCable->SetupAttachment(RootComponent, FName("HookSocket"));
	HookCable->CableLength = 0.0f;
	HookCable->CableWidth = 4.0f;
	HookCable->NumSegments = 10;
	HookCable->SolverIterations = 2;
	HookCable->SetVisibility(false);
	HookCable->EndLocation = FVector(0.0f, 0.0f, 0.0f);

	bHooked = false;
	bHookedFinished = false;

	HookLocation = FVector(0.0f, 0.0f, 0.0f);
}

//////////////////////////////////////////////////////////////////////////
// Input

void ARandomStuffsCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	// Set up gameplay key bindings
	check(PlayerInputComponent);

	PlayerInputComponent->BindAction("Hook", IE_Pressed, this, &ARandomStuffsCharacter::StartHook);
	PlayerInputComponent->BindAction("Hook", IE_Released, this, &ARandomStuffsCharacter::StopHook);
}

void ARandomStuffsCharacter::StartHook()
{
	FCollisionQueryParams TraceParams(TEXT(""), false, GetOwner());
	FHitResult HitResult;

	FVector StartLocation = GetMesh()->GetSocketLocation(FName("HookSocket")); //HookCable->K2_GetComponentLocation();
	FVector EndLocation = StartLocation + (GetViewRotation().Vector() * HookLength);

	bool bHitActor = GetWorld()->LineTraceSingleByObjectType(
		HitResult, 
		StartLocation, 
		EndLocation,
		FCollisionObjectQueryParams::AllObjects,
		TraceParams
	);
	DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Red, true, -1.0f, 0, 1.0f);

	if (bHitActor)
	{
		bHooked = true;
		HookLocation = HitResult.ImpactPoint;
		DrawDebugBox(GetWorld(), HitResult.ImpactPoint, FVector(6), FColor::Purple, true, -1.0f, 0, 5.0f);
	}
	else
	{
		StopHook();
	}
}

void ARandomStuffsCharacter::StopHook()
{
	bHooked = false;
	bHookedFinished = false;

	HookCable->SetVisibility(false);
	HookCable->GetRelativeTransform().SetLocation(FVector(0, 0, 0));
}

bool ARandomStuffsCharacter::MoveRope()
{
	FVector HookWorldLoc = GetMesh()->GetSocketLocation(FName("HookSocket"));
	HookCable->SetVisibility(true);

	DrawDebugBox(GetWorld(), HookWorldLoc, FVector(3), FColor::Yellow, true, -1.0f, 0, 1.5f);
	DrawDebugBox(GetWorld(), HookLocation, FVector(3), FColor::Green, true, -1.0f, 0, 1.5f);

	FVector Distance = HookWorldLoc - HookLocation;
	if (Distance.Size() <= 100)
	{
		return true;
	}
	else
	{
		HookCable->GetRelativeTransform().SetLocation(FMath::VInterpTo(HookWorldLoc, HookLocation, GetWorld()->GetDeltaSeconds(), 1));
		return false;
	}
}

void ARandomStuffsCharacter::MovePlayer()
{
	FVector PlayerLocation = GetTransform().GetLocation();
	FVector LaunchVel = ((HookLocation - PlayerLocation)) * ((GetWorld()->GetDeltaSeconds() * 15));

	LaunchCharacter(LaunchVel, true, true);
}

void ARandomStuffsCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (bHooked)
	{
		if (bHookedFinished)
		{
			FVector NewLocation = FMath::VInterpConstantTo(
				HookCable->GetRelativeTransform().GetLocation(),
				HookLocation,
				GetWorld()->GetDeltaSeconds(),
				250
			);
			MovePlayer();
			HookCable->GetRelativeTransform().SetLocation(NewLocation);
		}
		else
		{
			bHookedFinished = MoveRope();
		}
	}
}