Multiplayer physics lag

In the video above, youll see a small demo of my game. Youll notice when the client and server take turns driving the ship, the server player looks perfectly fine on the clients screen.
When the client drives, the server player will see him lag behind a bit. Im not sure whats causing this, but ill include screenshots of my code and kinda explain whats going on

game mode
UE-GM

pawn

I set the UpdateGrav function to always be called from am EventDispatcher. I did this because Im under the assumption all the players will receive the signals individually(in a multithreaded way) and will hopefully will prevent some lag.

pawn grav

For the gravity, the first photo is getting the ship the player is currently attached to and applying their velocity to themselves. When the player is standing still, the branch is true, and it applies a force that bring the player to the spot they stopped walking on.

Blueprint is meant for prototyping and basic level code only, not for final playable code. As such, there’s always going to be additional lag introduced to a multiplayer game if it’s coded with BP. If your game is very reliant on a lag-free connection, the only true way to solve this is by coding it in C++.

Will that actually solve it? I havent moved to C++ because I wanna find the right system that works first.

So I have zero experience with C++ and multiplayer, but my guess is yes. There’s a custom movement on the marketplace that sells for $400+ and I was watching one of his videos where he was describing the issue with BP. He was saying that basically running MP code in BP will introduce lag and the character position won’t update properly (and he definitely knows what he’s talking about).

Here’s the video where he discusses the lag: (Skip to 16:25 mins in and watch from there)

The lag introduced by a good blueprint implementation is no more than a frame compared to C++.

The main problem is that the client is on the other side of a network from the server. If you want to reduce the lag as much as possible, the client and server need to be wired to the same wired network, and you have to make the network tick rate faster than the frame rate, and make sure you set all your important objects (clients) to have the appropriate very-high network update frequency.

In general, though, physics based on direct client interaction will always be laggy, because of the various asynchronous steps involved (client input, client simulate, client render, network packet building, network transmission, network receive, server simulate, server render) which all may cause delays that end up accumulating. The only solution is to design your game rules such that latency is hidden, and implement your game animations such that the other players don’t notice.

My favorite in hiding latency, is the “yes, sir!” animation that units play when you give them orders in RTS games, before they move out. That animation is only played for players that give the order, and by the time the animation/clip has played out, everybody has the command/message, and the unit can actually start moving. This extreme measure is absolutely needed by RTS games that use lockstep synchronization, and the same mechanism can also be used in interpolated engines like Unreal, although the outcome in Unreal if you miss it is just that objects look laggy, not full game de-sync like you’d get in a RTS game.

1 Like

I was able to replicate the lag problem by just moving a platform the players are standing on. It’s a network latency issue, not performance issue.

Explanation

What I think is happening is that when the client drives, because the client’s character isn’t actually moving on it’s own (it’s standing on the ship), the server doesn’t know that the client’s character should move. So, from the server’s perspective, the client’s character stays in the same place. When the ship movement is replicated to the client, the client’s character follows the ship and is replicated back to the server many frames after the ship has already started moving on the server, causing lag.

From the client’s perspective when the server drives, both the server’s character and the ship move at the same time and are replicated to the client correctly.

You may be able to solve this by attaching/parenting the driver to the ship like you would a vehicle. That way, all players have the driver attached locally so it won’t lag.


Other ideas

Relying on physics like this may not be good. Think about when you have more complex situations like walking on stairs, going inside the ship, large collisions with other ships, or having physically simulated objects on the ship (which will never go to sleep because they’re always moving). I also noticed in your videos that the client’s camera is more bouncy & unstable than the server’s camera (which seems perfectly still).

Consider putting all objects on a ship in “ship space” like I do here. The player is actually hidden under the map (but for a space scene, you can set it to hidden in game). The player you see is a “clone” that copies the transforms and animations of the real character. The real character is always upright, whereas the clone moves & rotates with the ship because it’s parented to it (it’s a skeletal mesh component in the ship blueprint). This keeps you from having to worry about complex interactions & physics on the ship because they all happen in “ship space.” Though, it does have the problem of how to “detach” from the ship when you want to float out into space and interact with things outside the ship. It’s possible, but can it be done seamlessly?

Haven’t tested it in multiplayer, but it should work the same: just copy the real characters’ transforms to clones inside the ship. Because the real characters aren’t actually moving, you shouldn’t get any lag problems.


If not that, you should probably consider attaching the (real) characters to the ship (by parenting, setting location manually, etc.) only when they’re standing on it, and detaching them (while keeping the momentum of the ship) when they’re not.

So basically just the same the solution for attaching the driver to the ship, but for all players whenever they’re standing on the ship.

Im probably gonna go with the attaching as I need the players to be able to actively leave and run around the ship. Had issues with it earlier and was hoping to get away with the physics, but oh well