Pawn possession brakes movement replication

Hello. I have a boat than uses physics simulation on server + movement replication. I can possess it to control. After I do, on client who possessed the boat its movement after some time becomes super choppy, even if I stop it and do not move any more. the most interesting thing here is that on other client who does not possessed the boat - the movement is always very smooth and correct.

Experimentally I realized that this happens only when I possess the boat. If I will again possess character - movement lag immediately disappears. And so on.

Looks like the PlayerController or something else tries to change the rotation or location in addition to physics movement replication. This is my version, but I did not found any code to prove it.

Please note that all “UseController Yaw Pitch Roll” - are turned off.

Also, if I possess the character and run onto the boat - again, my character movement is a bit choppy when I stops, but all characters that I do not own always moves perfectly. So replicated movement works better then my own))

Looks like I need to code the game without trying to possess anything))) But this is not possible) So, maybe someone knows what is the problem here? What can I miss? I checked Actor.cpp, Pawn.cpp, ActorReplication.cpp - not additional SetRotation or similar is called.

I’m afraid you have stumbled into an area that is much more difficult to solve than you may be aware of. Physics objects in particular make this MUCH more difficult.

Possession isn’t really the problem - the problem is that as a client who is in control of the actor, you are trying to tell the server what the simulation is doing. However, the server is also doing this in the meantime and sending the results back to the client. As lag / packet loss increases, you get updates much later, and the result will conflict with that the local simulation thinks is happening, and the client will constantly be snapping to prior positions. The reason it’s smooth on non-local clients is because they’re only getting updates from the server and snapping between them. As you’re simulating physics, the physics engine handles the “blending” by continuing the simulation.

There are two ways to go about fixing this. The first is to create your own non-physics movement component which mimics what Character Movement Component does. This is a big topic and Character Movement is not widely understood by everybody (fortunately I’ve spent a bit too much time doing this kind of thing). This is arguably the most difficult “fix”, but will give you the best results in the end. I warn you in advance that Character Movement is very complex and hard to understand. It took me a few attempts to get my own movement components working. It has prediction, reconciliation and smoothing and is server-authoritative - all of which are essential for good online movement. It does NOT support Physics-objects, but it is currently not possible to do this kind of movement with Physics objects in Unreal.

The other much easier solution is to continue using movement replication and physics, but use a client authoritative system. In the client who controls the actor, you override the PostNetReceiveLocationAndRotation() function to NOT apply the server values to that local client, and you also call an unreliable Server RPC each tick to tell the server where the client thinks the boat is. This is known as client-authoritative simulation and is completely open to cheating unless you add some sanity checks.

For Physics, the latter is currently your only option as even Character Movement doesn’t handle the complex nature of Physics objects.

I am working on a more “generic” online movement system which will be available in the future to neutralize this problem a bit, but it’s not going to be ready for quite a while I’m afraid!

Thank you for your answer. Maybe it makes sense for me to fake most of the movement to achieve better replication.

But still about what you just said, іs there really no way just to force local pawn to only receive updates like non-local clients do? If this is already implemented…

I’m not sure if I’ve fully understood the problem but if you’re having issues with the client and server both simulating physics (as a result of client prediction) and the client being snapped back to the server’s position when it receives updates, then there is something you can do to alleviate the snapping.

on receive position update from server
    find difference between your position and the server's update

    if the distance is > some threshold (let's say 2 meters)
        snap client's position to server's position
    eles if distance is > 0.5 (let's say 0.5 meters)
        move 10% of the distance between client's position and server's position

    snap client velocity to server's velocity  

    clear acknowledged moves (this is all the moves that have a timestamp < the server's updated move timestamp)

    simulate the unacknowledged moves (all the moves that were saved in our buffer which have a timestamp > the server's updated move timestamp)

This means whenever the client receives an update from the server, it checks the unacknowledged moves buffer and compares its physics state at that time with the server’s update. If they differ vastly, snap the position of the client and simulate the rest of the unacknowledged moves from a CORRECTED position.

You may find this link useful Networked Physics (2004) | Gaffer On Games