Shooter Dedicated Server Lag

Hi,

Running the stock Shooter sample and checking the “Dedicated Server” box in the editor preview, I get lots of lag. It’s most obvious when turning your character; the 1st person weapon model will jitter back and forth.

Hi Stefan Lundmark,

Thank you for letting us know, I was able to reproduce this and have put in a bug report to be assessed with this and my findings attached. thank you and have a great day!

I get the same issue always in clients, even if I’m not using a dedicated server. It probably has something to do with network latency, though not because of bad lag; it looks like its fighting with something else that’s trying to set its position and rotation. I’ve tried to reset it on movement replication but that didn’t seem to do anything.

Here’s a fix in case you don’t want to wait for Epic.

The problem lies in OnCameraUpdate. This function would only get called on the client but relies on the actor’s location and rotation, which would be replicated. This is just a guess, but no matter what the latency is, things would run a bit behind and the client would end up fighting on what the correct position and orientation should be.

The fix is to change OnCameraUpdate to not rely on replicated positions or orientations. There are two places where this would happen.

First, is the LocalToWorld matrix. You would have to move that line right after RotCameraYaw and modify it accordingly:

const FMatrix LocalToWorld = FRotationMatrix(RotCameraYaw) * FTranslationMatrix(CameraLocation + FVector(0.0f, 0.0f, -64.0f));

This would create a matrix that’s similar to ActorToWorld(), while only relying on values created by the client. The -64 Z offset I’ve grabbed from observation, I’m not sure where it comes from.

The next problem is the call to SetRelativeLocationAndRotation at the end. You can pass in values that are independent from replication, but it would be set relative to the actor’s location and rotation, which would be replicated values. We need to set the location in absolute coordinates using SetWorldLocationAndRotation, as so:

Mesh1P->SetWorldLocationAndRotation(LocalToWorld.GetOrigin() + PitchedMesh.GetOrigin(), PitchedMesh.Rotator());

Since we’re setting an absolute rotation, we need to apply the yaw of the camera to PitchedCameraLS:

const FMatrix PitchedCameraLS = FRotationMatrix(RotCameraPitch) * FRotationMatrix(RotCameraYaw) * LeveledCameraLS;

That should solve the twitchy/laggy movement on the first person view model. The final modified function should look like this:

	USkeletalMeshComponent* DefMesh1P = Cast<USkeletalMeshComponent>(GetClass()->GetDefaultSubobjectByName(TEXT("PawnMesh1P")));
	const FMatrix DefMeshLS = FRotationTranslationMatrix(DefMesh1P->RelativeRotation, DefMesh1P->RelativeLocation);

	// Mesh rotating code expect uniform scale in LocalToWorld matrix

	const FRotator RotCameraPitch(CameraRotation.Pitch, 0.0f, 0.0f);
	const FRotator RotCameraYaw(0.0f, CameraRotation.Yaw, 0.0f);
	// we need to depend on location/rotation that originated from the client, not anything that may have been replicated
	// otherwise, we'd have some twitchy behaviour on the first person model
	const FMatrix LocalToWorld = FRotationMatrix(RotCameraYaw) * FTranslationMatrix(CameraLocation + FVector(0.0f, 0.0f, -64.0f));

	const FMatrix LeveledCameraLS = FRotationTranslationMatrix(RotCameraYaw, CameraLocation) * LocalToWorld.InverseSafe();
	const FMatrix PitchedCameraLS = FRotationMatrix(RotCameraPitch) * FRotationMatrix(RotCameraYaw) * LeveledCameraLS;
	const FMatrix MeshRelativeToCamera = DefMeshLS * LeveledCameraLS.InverseSafe();
	const FMatrix PitchedMesh = MeshRelativeToCamera * PitchedCameraLS;

	Mesh1P->SetWorldLocationAndRotation(LocalToWorld.GetOrigin() + PitchedMesh.GetOrigin(), PitchedMesh.Rotator());

Obvious improvements are better math and finding out where the -64 Z offset comes from.

Has this been fixed in 4.2? It isn’t mentioned in the release notes.

Hi Stefan,

This is still currently being assessed. Thank you for your patience while we address this bug.

I tested your fix and it seems to work fine, although I’m not fully understanding it yet. I do appreciate that you’re trying to explain it as well, really nice.

Thanks a lot!

I fixed a related issue on 4/28/2014, I can’t be sure it is the same thing you are seeing, but it sounds very similar. This would have made it to the 4.2 release so please confirm whether you are still seeing it.

In this case the problem was client move-combining that is done to lower bandwidth of client moves to the server. There was a bug that was causing the wrong rotation to be set after a move was reverted and then combined (in UCharacterMovementComponent::ReplicateMoveToServer().

It was possible to work around this bug before by using the console command “p.NetEnableMoveCombining 0” in-game on the client. If you are still testing on 4.1 or earlier try that command and see if that fixes it for you, in which case the 4.2 update should solve it. If not, then it is a different bug.

Hi Zak, thanks for taking the time. Using the console command “p.NetEnableMoveCombining 0” does indeed get rid of all the jitter in 4.1. I’ll be updating to 4.2.

Thanks again!