Advertisement

Source Multiplayer Networking - Need help to understand input prediction vs authoritative server.

Started by January 10, 2022 08:27 AM
4 comments, last by agleed 2 years, 10 months ago

Hi,

I read this article https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking, and I am struggling to understand how client synchronizes itself with the server when it performs prediction.

More precisely, the client performs prediction of player behavior according to current inputs without waiting for the server computation. But in this case, it means that the client is ahead on time compared to the server.

When the client receives a server state update, what does it do?

Does it updates its state without taking into account user inputs? As it was ahead of time, maybe the current state update does not contain the effect of the last user input.

Does it wait for an update that take into account the user input? But in this case, as there may always be new inputs, the server state is always delayed compared to the prediction.

--> position received is always obsolete.

Also, in the article, they explained that rendering is 100ms late compared to the simulation. Where is the user input prediction taken into account?

At the client simulation time (so with a 100ms lag due to rendering being late) or at the rendering time?

My understanding:

the client never synchronizes the state of entities for which it has predicted the behavior (I mean it does not just copy paste the server state).

It keeps history of its prediction, and when it received server updates, it checks that its past predictions were correct (not current one as it is already predicting new commands...)

If the past prediction were bad, it rewinds its state to the tick corresponding to the discrepency and recompute prediction with new commands.

So for the user's entities, client side is ahead of time compared to the server. For the other entities, client is late compared to the server.

Thanks in advance for any help, and sorry for my english i did my best.

Franc'

The next article uses the Valve article: http://buildnewgames.com/real-time-multiplayer/

Source code of the example from the article: https://github.com/ruby0x1/realtime-multiplayer-in-html5

Demo of the example: https://battle-world.herokuapp.com/?debug

Advertisement

mop_fbm said:
When the client receives a server state update, what does it do?

In this model of server authority, the client always adjusts itself to match what the server has. The server is the authority, and while they client can predict what is happening, it doesn't know about what is happening on other clients until it gets updates from the server. Both client and server also must recognize lag, so clients following this model should allow for motion.

How it looks depends on the game. Rubber-banding (having objects slide/jump to the right position) is common these days. In some games it can also trigger local animation work like walking/running to the target location rather than rubber-banding.

Accounting for tolerance of latency is also game-specific. When a client receives the server's authoritative data, it is data from when the server sent it, which may be one or two graphics frames in the past. If the game were to pop the position to exactly where the server said it was the moment it received it, the game might be placing it in the historical position rather than the current position. Engines like Unreal have invested a lot of development work toward the problem.

mop_fbm said:
Also, in the article, they explained that rendering is 100ms late compared to the simulation. Where is the user input prediction taken into account? At the client simulation time (so with a 100ms lag due to rendering being late) or at the rendering time? …

It's all relative. The server seems to live in the future from the game's perspective. The clients seem to live in the past from the client's perspective.

Ultimately it all boils out and doesn't particularly matter except for how you imagine it in your mind. Ultimately the server gets data over a small time window, applies the data in a simulation step, then updates the clients. Clients draw what they think the world looks like but understand they only have a limited view, so clients constantly correct based on what the server says. Anything more about what is “now”, about past or future, that's for you rather than the model. Thinking about it as being in the past or future, thinking of it being late, if that helps your mental model then use it, otherwise don't. If you can internally think about latency in those terms or in other terms, go for it.

mop_fbm said:
If the past prediction were bad, it rewinds its state to the tick corresponding to the discrepency and recompute prediction with new commands.

Yes, that's basically the approach several games use. This approach isn't universal. It's more common in big shooters and active games, less common in social games and smaller projects, and is seldom used in turn based games. Determining how authority works in games is a critical step, but not all games run as dedicated authoritative servers.

I've used a variety of techniques in games I've worked on. Sometimes there can even be multiple at once. Even in the same game we can have elements that follow one pattern and elements that follow another pattern.

It's fairly straightforward except for FPS games. A low end solution is that turning is local but moving involves a round trip to the server. This is a bit laggy but avoids rubbber-banding.

In FPS games, hits have to be detected on the server, or people will hack the client and cheat. But the player's view of the opponent's position may be delayed from where the server has the opponent positioned. So the player shoots at the opponent, sees a hit locally, and then the server registers that as a miss. Player is angry.

I've seen a good article on how to deal with this, but don't have the reference handy. The general idea is that the server has to track not only where the opponent is, but where each client thinks the opponent is, based on the last update sent to the client and the elapsed time. Hits are evaluated against that position. This way, if the player sees a hit, the server registers a hit. Player is happy.

Now this creates a problem for the opponent's client. Opponent is running to avoid being hit, and suddenly ducks. Before the duck update reaches the player's client, the player shoots and sees a hit. The server evaluates the hit based on what it has told the client. But the opponent sees a hit registered against them, even though they ducked. Opponent is angry. Although they are less likely to notice than the shooter.

Somebody more into FPS games can probably elaborate on this.

mop_fbm said:

When the client receives a server state update, what does it do?

To keep prediction going and stop you from rubberbanding constantly, you keep a buffer of all your past inputs back to when you received the last update (up to a certain limit). When you receive an update from the server, you reset your state to whatever the server sent you and then replay your inputs from that moment up to your latest recorded input (all updates and inputs are timestamped with a tick counter).

If your predictions in the past were correct and your update logic is somewhat deterministic, nothing will visibly change because the replayed state will be exactly the same. If there was a misprediction (because something you didn't know about on the client side interacted with your server-side state) your state will diverge from the point of the update and the replayed inputs will have you end up in a different state, but probably closer to the predicted state than if you hard-reset to the received server update every time.

This topic is closed to new replies.

Advertisement