Server reconciliation for multiplayer FPS game

Started by
3 comments, last by Hodgman 6 years, 11 months ago

Reading the usual resources on multiplayer games (1, 2, 3); I have started working on my own multiplayer game.

I used a naive approach that for every input I receive from a client, I immediately run it on the server.

For simple units (soldiers) everything works well, however I have an issue with "always moving" units (such as jet fighters); They require queuing inputs on the server (small delay, less than 100ms)and performing them in delay - and I read elsewhere (1, 2) that you should allow a window to receive inputs longer than said delay, since latency is variable (and could easily reach over 100ms) and reconcile the player's input.

Now I understand how this works for simple input such as movement, but what about using weapons / more advanced input?

What happens if player input came in delay, where he wishes to fire his weapon - what do I do? When do I notify other players of the shot? What about it's result? What if my cool-downs are out of sync due to this reconciliation?

Thanks!

Advertisement

I've never heard of this being implemented as a server delay before. I don't see a reason for doing this, in your case or any case. Nor should it have to be handled differently for vehicles and players; both are typically just physics-based objects that move around with some degree of velocity and momentum.

What is more common is that clients see things slightly delayed, partly due to unavoidable latency from the server but also with a little extra added to allow smooth interpolation between multiple state snapshots that arrive a small time apart. And what is also common is that the server can process an individual event as if it took place in the past, so that it is more consistent with the relevant player's experience, but that's not done by running the whole server on a delay. (Because that would not help; all it does is increase the effective latency between a client action and other clients receiving it.)

I can't answer your other questions because it's all "it depends on what you want to do", and is complicated by this server-side delay you mention. Many FPS games send out state updates as soon as possible, their clients render the world state slightly in the past to enable smooth blending between state snapshots, and the server resolves important events such as attacks by remembering where everything was at the time the attack was launched (given a reasonable assumption about player latency) even though players may have seen something slightly different on their screens since then. Do you think that won't work for you?

The server side window acts as a limit to how far back the server is willing to rewind. This stops abuse/glitches ("I shot that guy 10 seconds ago!") and puts a limit on how much state the server has to keep buffered.

When the server gets a complex input such as shooting, it rewinds the gamestate the the point in time when the event was generated and then plays back the event, and then fast-forwards back to the present. It's basically a git merge operation :)
During this process, it may reject impossible events, such as if a player has died right before they try to shoot. Any events that weren't rejected are broadcast to all clients in the next state update.

The client that generates the event plays it immediately (e.g. gunshot sounds/animations) but this is only a prediction. Perhaps the player is already dead but doesn't know it. The server eventually responds with whether their event was accepted or not, and in the latter case, the client has performed a misprediction and needs to change their local gamestate to match the server (cancel the sounds/animations, plus perform any other updates, such as dying instead).

I've never heard of this being implemented as a server delay before. I don't see a reason for doing this, in your case or any case. Nor should it have to be handled differently for vehicles and players; both are typically just physics-based objects that move around with some degree of velocity and momentum.

What is more common is that clients see things slightly delayed, partly due to unavoidable latency from the server but also with a little extra added to allow smooth interpolation between multiple state snapshots that arrive a small time apart. And what is also common is that the server can process an individual event as if it took place in the past, so that it is more consistent with the relevant player's experience, but that's not done by running the whole server on a delay. (Because that would not help; all it does is increase the effective latency between a client action and other clients receiving it.)

I can't answer your other questions because it's all "it depends on what you want to do", and is complicated by this server-side delay you mention. Many FPS games send out state updates as soon as possible, their clients render the world state slightly in the past to enable smooth blending between state snapshots, and the server resolves important events such as attacks by remembering where everything was at the time the attack was launched (given a reasonable assumption about player latency) even though players may have seen something slightly different on their screens since then. Do you think that won't work for you?

Hey thanks for your answer; state interpolation is relevant to remote players, I'm speaking about the problem of the player himself.

Assuming I am playing an "always moving" unit such as a jet fighter, what happens if I my latency is too high or too variable? If I don't use some sort of loop to process inputs on the servers, the jets will appear to be lagging for all players if no input is received.

The server side window acts as a limit to how far back the server is willing to rewind. This stops abuse/glitches ("I shot that guy 10 seconds ago!") and puts a limit on how much state the server has to keep buffered.

When the server gets a complex input such as shooting, it rewinds the gamestate the the point in time when the event was generated and then plays back the event, and then fast-forwards back to the present. It's basically a git merge operation :)
During this process, it may reject impossible events, such as if a player has died right before they try to shoot. Any events that weren't rejected are broadcast to all clients in the next state update.

The client that generates the event plays it immediately (e.g. gunshot sounds/animations) but this is only a prediction. Perhaps the player is already dead but doesn't know it. The server eventually responds with whether their event was accepted or not, and in the latter case, the client has performed a misprediction and needs to change their local gamestate to match the server (cancel the sounds/animations, plus perform any other updates, such as dying instead).

Hey Hodgman, I believe you're referring to lag compensation in regards to relieving aiming issues with latency.

Please read the example I wrote above, hopefully it explains my problem better.

Steering the jet works the same as shooting. Say you've got four bytes - pitch, yaw, roll and throttle. The client will send a stream of packets to the server containing timestamps and those 4 bytes. The server does the same rewind/apply/fast-forward to apply those user inputs to the jet simulation.
If no packets are dropped/rejected, then no matter the lag, the client's predicted state and the server's actual state will match.
If the lag is too high, the inputs will be too far in the past (outside the lag compensation window) so the server will apply the event at the limit of this window instead of at the time predicted by the client. The user will still be able to fly the jet, and other non-lagging clients will see the jet flying smoothly... But the laggy client who is flying the jet will see a breakdown in client-side prediction, where the jet has to be "rubber banded" constantly from the incorrectly predicted position to the server's authoritative position.

FWIW 100ms is a pretty small window. One side of the US to the other is probably about 100ms, but could be a bit higher, especially if the user is on poor infrastructure. Crossing the pacific or the Atlantic is another 100ms. Many games support international play where pings can be around 300-450 from one side of the world to the other.

This topic is closed to new replies.

Advertisement