When the player shoots he performs a RayCast that I show for debugging purposes. This is the code for the function StartFire()
FVector CameraLoc;
FRotator CameraRot;
Cast<APACharacter>(GetOwner())->GetActorEyesViewPoint(CameraLoc, CameraRot);
FVector ShootDir = CameraRot.Vector();
const float ProjectileAdjustRange = 10000.0f;
const FVector StartTrace = GetCameraDamageStartLocation(ShootDir);
const FVector EndTrace = StartTrace + (ShootDir * ProjectileAdjustRange);
FHitResult HitResult = WeaponTrace(StartTrace, EndTrace);
**DrawDebugLine(GetWorld(), Start, End, Color, true, -1, 0, 0.7f); // this is the debug/visible RayCast line**
In order to fully understand the code above, you need **GetCameraDamageStartLocation() **and WeaponTrace() functions;
FVector APAWeapon::GetCameraDamageStartLocation(const FVector& AimDir) const
{
APlayerController* PC = Cast<APACharacter>(GetOwner()) ? Cast<APlayerController>(Cast<APACharacter>(GetOwner())->Controller) : nullptr;
FVector OutStartTrace = FVector::ZeroVector;
if (PC)
{
FRotator UnusedRot;
PC->GetPlayerViewPoint(OutStartTrace, UnusedRot);
}
return OutStartTrace;
}
************************************************************************
FHitResult APAWeapon::WeaponTrace(const FVector& StartPlug, const FVector& EndPlug, const TArray<AActor*>& IgnoreActors) const
{
static FName WeaponFireTag = FName(TEXT("WeaponTrace"));
// Perform trace to retrieve hit info
FCollisionQueryParams TraceParams(WeaponFireTag, true, Instigator);
TraceParams.bTraceAsyncScene = true;
TraceParams.bReturnPhysicalMaterial = true;
TraceParams.AddIgnoredActors(IgnoreActors);
FHitResult Hit(ForceInit);
GetWorld()->LineTraceSingleByChannel(Hit, StartPlug, EndPlug, COLLISION_WEAPON, TraceParams);
return Hit;
}
Now, the screenshots:
SERVER
The Trace lines up so perfectly with the Camera that you don’t see it. If you move laterally, though, you’ll see the Trace.
**CLIENT
On the Client, though, it’s a bit out-of-phase. It’s not lined up like in case of the Server.
The function containing all of this is called from a Server RPC call of this kind:
if (Role < ROLE_Authority)
ServerHandleFiring();
else
{
............ do the trace ............
}
Here ServerHandleFiring() is just the Server RPC function which calls **StartFire() **(this time, as the Server)
UFUNCTION(reliable, server, WithValidation)
void ServerHandleFiring();
void ServerHandleFiring_Implementation();
bool ServerHandleFiring_Validate();
**How can I solve this?
Is there a better way to do it?**
Thanks in advance!