The last 3 or so videos have been centered around tracing a line from the crosshair to get a usable world location for our aiming mechanics. In a previous video, Ben suggested pseudo-coding a line-tracing function, but also left a “very advanced” challenge which was to make our line-tracing function actually fully functional. I accepted this challenge and discovered a function called GetHitResultAtScreenPosition() which accomplishes everything we need. It has a FHitResult out-parameter which we can use to get detailed information about our line trace, and allows us to filter trace queries by collision channel, object type, etc. just like the other line tracing methods do.
Here is my code for the crosshair line-tracing functions in question, which work flawlessly and even reports what we are looking at:
void ATankPlayerController::AimAtCrosshair()
{
if (!GetControlledTank()) { return; }
FVector HitLocation = FVector(0);
FString ObjectHit = "Nothing";
GetCrosshairTraceHit(ObjectHit, HitLocation);
UE_LOG(LogTemp, Warning, TEXT("Targeting: %s Location: %s"), *ObjectHit, *HitLocation.ToString());
}
bool ATankPlayerController::GetCrosshairTraceHit(FString &ObjectHit, FVector &HitLoc)
{
// Viewport Size
int32 ViewportSizeX, ViewportSizeY;
GetViewportSize(ViewportSizeX, ViewportSizeY);
bool bHit;
FVector2D CrosshairPosition = FVector2D(ViewportSizeX / 2, ViewportSizeY / 3);
FHitResult HitResult;
bHit = GetHitResultAtScreenPosition(CrosshairPosition, ECollisionChannel::ECC_WorldStatic, false, HitResult);
if (bHit)
{
HitLoc = HitResult.ImpactPoint;
ObjectHit = HitResult.GetActor()->GetName();
}
// Draws a red line for debugging purposes
DrawDebugLine(GetWorld(), HitResult.TraceStart, HitResult.TraceEnd, FColor::Red);
return bHit;
}