I don’t understand why we are using GetCameraLocation to find the beginning of the line trace. From my current understanding wouldn’t GetCameraLocation find the center of the camera object and not the vector of the pixel coordinates in space? It seems to me that the third parameter of DeprojectScreenPositionToWorld would have the actual location of the pixel in point space which should be the start of the vector trace. Hopefully someone can help me understand thanks!
Not Sure if I should edit or reply. I’ve run a little debugging and got the handy dandy DrawDebugLine Function out and it appears if I use the third parameter from the DeprojectScreenPositionToWorld function it draws a perfect line from the center of my crosshairs to 10km away. At least as far as I can tell. I’ll attach some screenshots and code for reference, it’s not the prettiest.
bool ATankPlayerController::GetSightRayHitLocation(FVector &HitLocation) const
{
// Found Crosshair Position In Screen Coordinates
int32 ViewportSizeX, ViewportSizeY;
GetViewportSize(ViewportSizeX, ViewportSizeY);
FVector2D ScreenLocation(ViewportSizeX*CrossHairXLocation, ViewportSizeY*CrossHairYLocation);
FVector LookDirection;
FVector LookLocation;
if(GetLookDirection(ScreenLocation, LookDirection, LookLocation))
{
GetLookVectorHitLocation(LookDirection, LookLocation, HitLocation);
}
// UE_LOG(LogTemp,Warning,TEXT("LookDirection: %s"), *LookDirection.ToString())
HitLocation = FVector(1.0f);
return true;
}
bool ATankPlayerController::GetLookDirection(FVector2D ScreenLocation, FVector &LookDirection, FVector &LookLocation) const
{
FVector CameraWorldLocation; // To Be Trashed
return DeprojectScreenPositionToWorld
(
ScreenLocation.X,
ScreenLocation.Y,
LookLocation,
LookDirection
);
}
bool ATankPlayerController::GetLookVectorHitLocation(FVector LookDirection, FVector &LookLocation, FVector &HitLocation) const
{
FVector PlayerViewPointLocation;
FRotator PlayerViewPointRotation;
FHitResult HitResult;
FVector EndLocation = LookLocation + (LookDirection * LineTraceRange);
FCollisionQueryParams TraceParameters(FName(TEXT("")), false, GetOwner());
FCollisionResponseParams ResponseParameters = FCollisionResponseParams();
DrawDebugLine(
GetWorld(),
LookLocation,
EndLocation,
FColor(255,0,0),
false, -1, 0,
5
);
if (GetWorld()->LineTraceSingleByChannel
(
HitResult,
LookLocation,
EndLocation,
ECC_Visibility,
TraceParameters,
ResponseParameters
))
{
UE_LOG(LogTemp,Warning, TEXT("Captain We've Hit something"))
return true;
}
else
{
UE_LOG(LogTemp,Warning, TEXT("Captain We've Got Nothing"))
}
return true;
}
I’m just about to test this out, your solution seems much simpler (and in fact I started to do this before I got stuck and followed Ben’s video, only to realise this is the most logical thing to do in the first place!)
If we’re already obtaining this information(CameraWorldPosition)… then why wouldn’t we keep it and use it when we need it?
I’ll post back once I work it out - might test both ways just in case to test whether they are different. Just trying to keep things simple… and avoid any unnecessary includes now that we have to name them all!