Actors are invisible to possessed vehicle too far from origin

More info, here are my logs. When Possessed “ViewTarget” is updated but “ViewLocation” isnt.

LogClass:Warning: WorldSettings::Viewer 0 = ShooterPlayerController_19 viewing PlayerPawn_C_283 at V(X=173469.00, Y=309277.00, Z=8987.00)
//Player Pawn Moves to Buggy
LogClass:Warning: WorldSettings::Viewer 0 = ShooterPlayerController_19 viewing PlayerPawn_C_283 at V(X=173407.00, Y=308911.00, Z=9007.00)
//Here  player Possesses  Buggy
LogClass:Warning: WorldSettings::Viewer 0 = ShooterPlayerController_19 viewing XiBuggyOrig_C_367 at V(X=173407.00, Y=308911.00, Z=9007.00)
LogClass:Warning: WorldSettings::Viewer 0 = ShooterPlayerController_19 viewing XiBuggyOrig_C_367 at V(X=173407.00, Y=308911.00, Z=9007.00)
//Buggy changes position but ViewLocation isn't updated
LogClass:Warning: WorldSettings::Viewer 0 = ShooterPlayerController_19 viewing XiBuggyOrig_C_367 at V(X=173407.00, Y=308911.00, Z=9007.00)

I found a hacky fix. I’m not posting this as an answer because it is too messy.

problem is in APlayerController::GetPlayerViewpoint override. or Actually in PlayerCamerManager->GetCameraViewPoint specifically. It doesn’t reliably set out_Location variable for possessed vehicles. It seems to work for camera, but not for relevance test that also uses this function.

My “Fix” is to check Pawn (Vehicles’s) GetActorLocation in an override of GetPlayerViewPoint and if it’ too far from return of GetCameraViewPoint, I use GetActorLocation response instead. Seems to not cause camera issues in tests either.

Hey Xilverback,

Sorry for delay in response. I apologize, I didn’t realize that it wasn’t updating ViewLocation at all, even if both Server and Client were together shortly before crossing that line. I see what you’re seeing now, and I’ve created a bug report for issue (UE-22390). I’ve included your notes, so thank you for thorough investigation! I’ll let you know when I see any update on bug report. Thanks!

, thank you for not forgetting about this. I really appreciate help.

Just a short update: issue seems to stem from fact that, while Characters set PlayerCameraManager->bShouldSendClientSideCameraUpdate = true;, Vehicles do not.

More precisely: relevant code is in CharacterMovementComponent.cpp at end of CallServerMove(). VehicleMovementComponent does not inherit this, as VehicleMovementComponent is derived from PawnMovementComponent.
By manually setting bool mentioned above to true in VehicleMovementComponent, this issue can be worked around.

issue was closed as “Won’t fix”, any information about why it won’t fix?

Hello or1on06,

You can find bug report on our public tracker here: Unreal Engine Issues and Bug Tracker (UE-22390)

It was marked as Won’t Fix due to a lack of activity for a prolonged amount of time. As you are interested in issue being fixed, I’ve reopened it.

4.20 made it worse, (Could’ve been 4.19) I upgraded from 4.18 to 4.20. After 3 years this is still not fixed. Now my workaround doesn’t work anymore. And my workaround now breaks my camera view. I’m back to square one and out of ideas. Feeling a bit disappointed guys.

Bug referenced says it’s fixed.
https://issues.unrealengine.com/issue/UE-22390

But code referenced here…
MarkForClientCameraUpdate();

Does not occur in 4.20 Code branch. Was it left out, forgotten, removed because of other problems?

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.

Thanks for posting that. I created a similar workaround but it has some other side-effects. Hope this is fixed in code base though. Multiplayer Vehicle support needs some attention.

Ok, I hacked it somehow. Seems that running Movement Component’s Add Input Vector on owner/multicast will tell Unreal that actor location has updated.

So I added an Add Input Vector node just after my multicast replication(should work on run on Owner too).
This node simply takes GetActorForwardVector x 0.000001 to get smallest vector, so that Unreal still updates location, but we don’t actually affect gameplay that much.

This is all in Blueprints by way. I don’t know if this fixes original problem, but my problem seemed to be same. Vehicle actors never becoming relevant if Character possessed them outside of Net Culling distance.