Line trace works once then fails there after

TankPlayerController_CPP.h

#pragma once

#include “CoreMinimal.h”
#include “Tank.h”
#include “Engine/World.h”
#include “GameFramework/Actor.h”
#include “GameFramework/PlayerController.h”
#include “TankPlayerController_CPP.generated.h”//MUST BE THE LAST INCLUDE

UCLASS()
class BATTLETANKS_API ATankPlayerController_CPP : public APlayerController
{
GENERATED_BODY()

public:
virtual void BeginPlay() override;

virtual void Tick(float DeltaTime) override;

UPROPERTY(EditAnywhere)
float CrosshairXLocation = 0.5f;

UPROPERTY(EditAnywhere)
float CrosshairYLocation = 0.3333f;

UPROPERTY(EditAnywhere)
float LineTraceRange = 1000000.0f;

private:
ATank* GetControlledTank() const;

void AimTowardsCrosshair();

bool GetSightRayHitLocation(FVector& OutHitLocation) const;

bool GetLookDirection(FVector2D ScreenLocation, FVector& LookDirection) const;

bool GetLookVectorHitLocation(FVector LookDirection, FVector &OutHitLocation) const;

};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

TankPlayerController_CPP.cpp

#include “TankPlayerController_CPP.h”//NEEDS TO BE FIRST INCLUDE
#include “BattleTanks.h”

void ATankPlayerController_CPP::BeginPlay()
{
Super::BeginPlay();

auto ControlledTank = GetControlledTank();

}

void ATankPlayerController_CPP::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UE_LOG(LogTemp, Warning, TEXT(“Start”));
AimTowardsCrosshair();
UE_LOG(LogTemp, Warning, TEXT(“End”));
}

ATank* ATankPlayerController_CPP::GetControlledTank() const
{
return Cast(GetPawn());
}

void ATankPlayerController_CPP::AimTowardsCrosshair()
{
if (!GetControlledTank()) { return; }

FVector OutHitLocation;


if (GetSightRayHitLocation(OutHitLocation))
{
	UE_LOG(LogTemp, Warning, TEXT("2_AimTowardCrosshair after OutHit: %s"), *OutHitLocation.ToString());
}		

}

bool ATankPlayerController_CPP::GetSightRayHitLocation(FVector& OutHitLocation) const
{

int32 ViewportSizeX, ViewportSizeY;

GetViewportSize( ViewportSizeX, ViewportSizeY );

auto ScreenLocation = FVector2D(ViewportSizeX * CrosshairXLocation, ViewportSizeY * CrosshairYLocation);

FVector LookDirection;

if (GetLookDirection(ScreenLocation, LookDirection))
{
	
	GetLookVectorHitLocation(LookDirection, OutHitLocation);
}
return true;

}

bool ATankPlayerController_CPP::GetLookVectorHitLocation(FVector LookDirection, FVector& OutHitLocation) const
{

FHitResult hitResult;

auto StartLocation = PlayerCameraManager->GetCameraLocation();

auto EndLocation = StartLocation + (LookDirection + LineTraceRange);


if (GetWorld()->LineTraceSingleByChannel(hitResult, StartLocation, EndLocation, ECollisionChannel::ECC_Visibility))
{		
	OutHitLocation = hitResult.Location;

	UE_LOG(LogTemp, Warning, TEXT("LineTraceSingleByChannel is true"));

	return true;
}
	UE_LOG(LogTemp, Error, TEXT("LineTraceSingleByChannel is false"));

	return false;

}

bool ATankPlayerController_CPP::GetLookDirection(FVector2D ScreenLocation, FVector& LookDirection) const
{
FVector CameraWorldLocation;

return DeprojectScreenPositionToWorld(ScreenLocation.X, ScreenLocation.Y, CameraWorldLocation, LookDirection);	

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

When I compile this and run it in the engine, I get this is the output log:

LogTemp: Warning: Start
LogTemp: Warning: LineTraceSingleByChannel is true
LogTemp: Warning: 2_AimTowardCrosshair after OutHit: X=791.720 Y=791.720 Z=791.720
LogTemp: Warning: End
LogTemp: Warning: Start
LogTemp: Error: LineTraceSingleByChannel is false
LogTemp: Warning: 2_AimTowardCrosshair after OutHit: X=0.924 Y=0.000 Z=0.000
LogTemp: Warning: End
LogTemp: Warning: Start
LogTemp: Error: LineTraceSingleByChannel is false
LogTemp: Warning: 2_AimTowardCrosshair after OutHit: X=0.924 Y=0.000 Z=0.000
LogTemp: Warning: End
etc…

I have scrubbed this a few times and I still can’t figure out where I am going wrong.

I’m ganna chalk this up to it being a difference in how unreal does things under the hood between 4.12 and 4.18. Since I am pretty sure this course was done in 4.11-4.12 and I am trying to follow along with 4.18. That being said, RyanPalmer’s suggested method for solving the same problem seems to stand the test of time, so if anyone is having the same issue as me, just find RyanPamlers post about a better way.

I would add on to agree with using the Ryan’s version as well. In my case, I am not able to get the right values for hit location using the lecture’s method but also not able to get 0 for the hit location when aiming at sky or something. I replaced it with Ryan’s and the values look ok but i still don’t get a 0 for far objects. The GetHitResultAtScreenPosition() does not take in a distance as criteria and so we need to filter the hit result to return false when distance is greater than the threshold. I still can’t get to print the 0 in the dist case > threshold and am not sure why it prints random values beyond the threshold but not 0.

Original

Change:
This fix the behavior in my testing. I don’t know if this will solve your issue but you need to multiply by lineTracerange:

auto EndLocation = StartLocation + (LookDirection * LineTraceRange);

Privacy & Terms