The Crosshair location and direction differ from hit location?

The crosshair location and direction differ from hit location, Why did that?

I used yellow DrawDebugLine to simulate the crosshair location and other one which is a red line for the hit location and the result is really strange.

I reviewed my c++ code step by step to discover the problem but every thing is as Mr @Ben did.

bool ATankPlayerController::GetSightRayHitLocation(FVector& HitLocation) const
{
	HitLocation = FVector(1.0);

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

	FVector OUT LookDirection;
	if (GetLookDirection(ScreenLocation, LookDirection))
	{
		GetLookVectorHitLocation(LookDirection, HitLocation);
	}

	return true;
}
bool ATankPlayerController::GetLookDirection(FVector2D ScreenLocation, FVector& LookDirection) const
{
	FVector OUT WorldLocation ; // To be discarded
	return DeprojectScreenPositionToWorld(
		ScreenLocation.X, 
		ScreenLocation.Y,
		WorldLocation, 
		LookDirection);
}
bool ATankPlayerController::GetLookVectorHitLocation(FVector LookDirection, FVector& HitLocation) const
{
	auto StartLocation = PlayerCameraManager->GetCameraLocation();
	auto EndLocation = StartLocation + (LookDirection * LineTraceRange);
	DrawDebugLine(GetWorld(), StartLocation, EndLocation , FColor::Yellow, false, 0, 0, 10);
	
	FHitResult OUT HitResult;

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

		DrawDebugLine(GetWorld(), StartLocation, StartLocation + (HitLocation.GetSafeNormal() * LineTraceRange), FColor::Red, false, 0, 0, 10);
		return true;
	}
	HitLocation = FVector(0);

	return false; // Line trace didn't succeed
}
1 Like

You’re doing the calculation incorrectly

(HitLocation - StartLocation).GetSafeNormal() * LineTraceRange

Thank @Dan but still have other problem:
The turret and barrel don’t move correctly !!

Look at this:

void UTankAimingComponent::MoveBarrelTowards(FVector AimDirection)
{
	auto BarrelRotator = Barrel->GetForwardVector().Rotation();
	auto AimAsRotator = AimDirection.Rotation();
	auto DeltaRotator = (AimAsRotator - BarrelRotator);

	Barrel->Elevate(DeltaRotator.Pitch);
	Turret->Rotate(DeltaRotator.Yaw);
}
void UTankBarrel::Elevate(float RelativeSpeed)
{
	auto ElevationChange = RelativeSpeed * MaxDegreesPerSecond * GetWorld()->DeltaTimeSeconds;
	auto RawNewElevation = RelativeRotation.Pitch + ElevationChange;
	auto Elevation = FMath::Clamp<float>(RawNewElevation, MinElevationDegrees, MaxElevationDegrees);
	SetRelativeRotation(FRotator(Elevation, 0, 0));
}
void UTankTurret::Rotate(float RelativeSpeed) 
{
	auto RotationChange = RelativeSpeed * MaxDegreesPerSecond * GetWorld()->DeltaTimeSeconds;
	auto Rotation = RelativeRotation.Yaw + RotationChange;
	SetRelativeRotation(FRotator(0, Rotation, 0));

}

Best way to see what’s wrong is with debug lines.

//TankAimingComponent
bool bHaveAimSolution = UGameplayStatics::SuggestProjectileVelocity
(
    this,
    OutLaunchVelocity,
    StartLocation,
    HitLocation,
    LaunchSpeed,
    false,
    0.f,
    0.f,
    ESuggestProjVelocityTraceOption::DoNotTrace,
    FCollisionResponseParams::DefaultResponseParam,    
    TArray<AActor*>(),
    true //DebugLine
);
//TankPlayerController
const static FName Tag(TEXT("TraceTag"));
GetWorld()->DebugDrawTraceTag = Tag;
FCollisionQueryParams Params(Tag);

if (GetWorld()->LineTraceSingleByChannel(
        HitResult,
        StartLocation,
        EndLocation,
        ECollisionChannel::ECC_Camera,
        Params)
)

Thanks @DanM :slight_smile:

auto BarrelRotator = Barrel->GetForwardVector().Rotation();
Why did we use GetForwardVector( ) with Rotation( ) for Barrel ? What would happen if delete GetForwardVector( ), i tried that but still do not understand the importance of it? Is there another way to do that ?

What is the relation between GetForwardVector and Rotation ?

auto AimAsRotator = AimDirection.Rotation();
In the same context, We did not use GetForwardVector with AimDirection !! Why ?

Your answer is V. important for me :slight_smile:

aslaamualaikum Bro how are you doing
you made good tank keep it up

1 Like

Well that part is redundant there you could just use GetComponentRotation. The only difference you would have there is that the way Ben did it doesn’t include Roll since GetForwardVector returns an FVector and you can’t work that out based on a vector.

GetForwardVector is the component’s forward vector. i.e. down the barrel. Then Rotation is getting the direction of that vector (again, excluding roll since you can’t get that from a vector)

Because AimDirection is already an FVector

1 Like

Thanks @DanM :slight_smile:

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms