Hi Xilverback
I bumped unto your question trying to correct exact same problem
Im using Unreal 4.20, and a pawn inherited vehicles using PhysX replication.
I modified IsNetRelevantFor in my PhysPawn code, and
added your sugested lines on PhysPawnMovementComponent PlayerCameraManager->bShouldSendClientSideCameraUpdate = true;
But ultimately i found that issue lies at PlayerController function ‘GetPlayerViewPoint’
You see, in NetworkDriver; ReplicationViewers you were talking about are created as TArray& ConnectionViewers;
FNetViewer ConnectionViewers are created by NetworkDriver for each client, by calling FNetViewer::FNetViewer Constructor, which sets Viewer’s (Other client proxy’s) ‘Location’ to that of its controller if it finds one with PlayerController function ‘GetPlayerViewPoint’
GetPlayerViewPoint(FVector& out_Location, FRotator& out_Rotation) const
;Then, sorts through an ‘if-else-if ladder’ searching for appropiate ViewTarget Location and Rotation.
In case of clients, their PlayerControllers have by default a PlayerCameraManager, this is option that gets selected; And again, PlayerCameraManager’s
GetPlayerViewPoint function gets called, which fills this ‘Location and Rotation’ info from its ‘GetCameraCachePOV()’ at which point, Location is already rounded to a Size limit in level.
This is what causes a discrepancy, since PlayerControlled Pawns/Characters/Vehicles are always replicated on client machine, obvioulsy, but proxies get culled by an error in distance…
Im telling you all this for you to know what could happen in next Unreal updates; My guess is that rounding of Location is for stability purposes, since most games do not cover large distances anyway.
TLDR:
Create a custom PlayerController class, override function GetPlayerViewPoint
virtual void GetPlayerViewPoint(FVector& out_Location, FRotator& out_Rotation) const override;
and simply comment out //PlayerCameraManager->GetCameraViewPoint(out_Location, out_Rotation); Line
void APhysPC::GetPlayerViewPoint(FVector& out_Location, FRotator& out_Rotation) const
{
//return;
if (IsInState(NAME_Spectating) && HasAuthority() && !IsLocalController())
{
// Server uses synced location from clients. Important for view relevancy checks.
out_Location = LastSpectatorSyncLocation;
out_Rotation = LastSpectatorSyncRotation;
}
else if (PlayerCameraManager != NULL &&
PlayerCameraManager->GetCameraCacheTime() > 0.f) // Whether camera was updated at least once)
{
//PlayerCameraManager->GetCameraViewPoint(out_Location, out_Rotation);//Comment this line
if (GEngine)
{
FVector DebugVector = out_Location;
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 0.0f, FColor::Green, FString::Printf(TEXT("GetPlayerViewPoint: %f, %f, %f"), DebugVector.X, DebugVector.Y, DebugVector.Z));
}
}
else
{
AActor* TheViewTarget = GetViewTarget();
if (TheViewTarget != NULL)
{
out_Location = TheViewTarget->GetActorLocation();
out_Rotation = TheViewTarget->GetActorRotation();
}
else
{
Super::GetPlayerViewPoint(out_Location, out_Rotation);
}
out_Location.DiagnosticCheckNaN(*FString::Printf(TEXT("APlayerController::GetPlayerViewPoint: out_Location, ViewTarget=%s"), *GetNameSafe(TheViewTarget)));
out_Rotation.DiagnosticCheckNaN(*FString::Printf(TEXT("APlayerController::GetPlayerViewPoint: out_Rotation, ViewTarget=%s"), *GetNameSafe(TheViewTarget)));
}
}
Hope this helps.