Top Down Template How to get the pawn to face the mouse direction.

I do it this way. Works a charm and even works if your cursor doesn’t hit a bit of the world (as its tracing against a virtual plane)



bool ATanksVsZombiesPlayerController::GetMousePositionOnAimingPlane(FVector& IntersectVector) const
{

	ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(Player);
	bool bHit = false;
	if (LocalPlayer && LocalPlayer->ViewportClient)
	{
		FVector2D MousePosition;
		if (LocalPlayer->ViewportClient->GetMousePosition(MousePosition))
		{
			bHit = GetPlanePositionAtScreenPosition(MousePosition, IntersectVector);
		}
	}

	if (!bHit)	//If there was no hit we reset the results. This is redundant but helps Blueprint users
	{
		IntersectVector = FVector::ZeroVector;
	}

	return bHit;
}

bool ATanksVsZombiesPlayerController::GetPlanePositionAtScreenPosition(const FVector2D ScreenPosition, FVector& IntersectVector) const
{
	// Early out if we clicked on a HUD hitbox
	if (GetHUD() != NULL && GetHUD()->GetHitBoxAtCoordinates(ScreenPosition, true))
	{
		return false;
	}

	FVector WorldOrigin;
	FVector WorldDirection;
	if (UGameplayStatics::DeprojectScreenToWorld(this, ScreenPosition, WorldOrigin, WorldDirection) == true)
	{
		IntersectVector = FMath::LinePlaneIntersection(WorldOrigin, WorldOrigin + WorldDirection * HitResultTraceDistance, GetPawn()->GetActorLocation(), FVector::UpVector);
		return true;
	}

	return false;
}


Then I use it in my tick like this



static const FName NAME_MouseAimingTrace("MouseAimingTrace");
void ATanksVsZombiesPlayerController::AimUsingMouseCursor() const
{
	if (!bMouseInput)
		return;

	// Check we have a proper pawn
	ATanksVsZombiesCharacter* Pawn = Cast<ATanksVsZombiesCharacter>(GetPawn());
	if (Pawn == nullptr)
		return;

	// Get the pawn location
	FVector PawnLocation = Pawn->GetActorLocation(); 
	
	// Trace to whats beneath the mouse cursor
	FHitResult OutTraceResult;
	//GetHitResultUnderCursor(ECC_Pawn, false, OutTraceResult);
	FVector IntersectVector;
	GetMousePositionOnAimingPlane(IntersectVector);

        // Trace down through the aiming plane to see if we hit an actor that we can aim at
	FCollisionQueryParams CollisionQueryParams(NAME_MouseAimingTrace, true);
	bool bHit = GetWorld()->LineTraceSingleByChannel(OutTraceResult, IntersectVector, IntersectVector - FVector::UpVector * HitResultTraceDistance, ECC_Pawn, CollisionQueryParams);
	
	
	// If we hit something aim set that as our aim direction, otherwise aim at the point on the plane
	FVector Direction = FVector::ZeroVector;
	FVector Location = bHit ? OutTraceResult.ImpactPoint : IntersectVector;

	if (Location != FVector::ZeroVector)
	{
		Direction = Location - PawnLocation;
		DrawDebugLine(GetWorld(), PawnLocation, Location, FColor(255, 0, 0), false, -1, 0, 10.0f);
		if (bHit)
			DrawDebugLine(GetWorld(), IntersectVector, OutTraceResult.ImpactPoint, FColor(255, 255, 0), false, -1, 0, 10.0f);
	}

	// Tell the pawn what its new aim direction is
	Pawn->SetAimInputVector(Direction);
}


SetAimInputVector goes through various functions to decide whether to use a joypad direction or the mouse direction, then consume it (reset it to zero vector) then lerp to it over time so things rotate rather than jump instantly. You may want to go back to your own code once you reach FVector Location =, as this is where the mouse cursor fell.