Client Side Prediction Correction During Collision produces different results on client and server

Hello,

I have client side prediction implemented in C++ for our airplane game and it works wonders. If a correction is neccessary, it is sent by the server, received by the client, all unacknowledged input is applied and stepped, and client and server end up on the same position again.

The only exception is that if a correction happens while the component has a collision, the server and client will sometimes come out with different positions after the correction has been sent from server to client and all unacknkowledged moves have been applied.

To clarify, the code is not using Unreal Physics, my movement is only based on Mesh->MoveComponent() and no other dynamic actors are present, the collision happens with static environment.

My suspicion is this is happening because the component keeps track of the overlaps of the previous frame and will act differently on server on client, because when the correction is received, the overlaps of the previous frame may be different on server and client and thus cause a different outcome for the call of MoveComponent() on my airplane. Is this correct? And if so, how can i make sure the outcome will be the same?

Here is an example of such a diversion with logs:

Server
Start Position: X=19830.823 Y=-5968.223 Z=59.895, Delta: X=2906.795 Y=2164.458 Z=-1808.154, Rotation: P=-2.760731 Y=-55.046479 R=24.172306, DeltaTime: 0.019504, End Location: X=19870.971 Y=-5938.328 Z=60.446
Client
Start Position: X=19830.823 Y=-5968.223 Z=59.895, Delta: X=2906.795 Y=2164.458 Z=-1808.154, Rotation: P=-2.760731 Y=-55.046479 R=24.172306, DeltaTime: 0.019504, End Location: X=19870.962 Y=-5938.335 Z=60.465

You can see the parameters are exactly identical for the function call, only the End Location (the Component World Location) differs afterwards.

Is there any pro that can help me out how to synchronize the states of server and client components so that they will calculate the same position after receiving an update again? Just to clarify, they are colliding with a static environment mesh, there are no other players around and the same code produces perfectly identical results if no correction happens during the collision.

Okay I found the problem, I was not logging the Start Rotation, only the Target Rotation and it turns out that the Start Rotation was not correctly synced to begin with. Further investigation turned out that the FRotator NetSerialize function is compressing the rotation and therefore leading to inaccurate results. Why this is limited to cases with collision I am not sure, but switching to FQuat fixes the issue, since FQuats do not compress values on NetSerialize.

1 Like

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