Latency and Input

Started by
1 comment, last by misterPhyrePhox 17 years, 10 months ago
To relay client input to the server in my game, the client will send a packet that consists of a bunch of input events; things like pressing a key or clicking a mousebutton. The events will be timestamped. But there's a problem; because of latency and packet loss, the events that the server receives will have happened in the past; if the server were to apply the events in the present, serverside simulation and clientside prediction would present two different views of the gameworld. The players control rigid bodies, so I was thinking of keeping maybe a 100ms history for each rigid body; when I received client input that happened in the past, I would rewind the rigid body and then apply the input, simulating up to the current time. But this is flawed in that, for example, say on the server the client collides with another object, but then the client sends input that occured in the past which would prevent that collision; if I only rewind the rigid body that the player controls, the other object will still have encountered that collision -- if the other object is a rigid body, maybe its velocity would have been affected by that collision. So do I have to keep a history of every object in the gameworld, and rewind the entire gameworld every time I receive client input that happened in the past? Am I overcomplicating things? Is there a simpler way to keep everything synchronized? (I realize that having clients timestamp their input events is potentially vulnerable, but I'll have logic on the server to reject outrageous timestamps.)
Advertisement
Yes, if you want an accurate simulation, you will have to keep a history of every object in the gameworld, at a reference point where you knew that all input had been received, and revert to that point every time some 'missed' input arrived.
Like you say rewinding the simulation would be a real headache. How would you actually decide whether some new input from requires a revert or not - run the rigid body simulation and see if there was a collision, and only then rewind? Remember you will need to rewind the whole simulation, not just one body. Using the timestamp from the client will be messy - say you get inputs from one client marked time x, rewind and run again. Then another clients inputs arrive also at time x so you could end up running the same timeslice of the simulation for every client.
How about a lock-step simulation, where information about inputs travels to the server and back before clients act on it - if your game can get away with having a response delay of one rtt after clicking the mouse or whatever, I think this is the most straightforward way. The bummer is the 'lock' part :) where everything will stop momentarily when network input is delayed.
I am doing this (based on the "1500 archers" article where clients send input for a 'game turn' instead of stamping a time on inputs) and it works nicely. I have not implemented physics on it yet, but I can't forsee any major difficulty with it (ask me in a few weeks time :). However my game will have inputs coming in at only a click or two every few seconds, and can have a reaction delay of a half-second or so before becoming irritating to the player. If your situation is more of a high speed action-game it might not be good enough.

1500 archers article
Quote:Original post by zppz
Yes, if you want an accurate simulation, you will have to keep a history of every object in the gameworld, at a reference point where you knew that all input had been received, and revert to that point every time some 'missed' input arrived.
Like you say rewinding the simulation would be a real headache. How would you actually decide whether some new input from requires a revert or not - run the rigid body simulation and see if there was a collision, and only then rewind? Remember you will need to rewind the whole simulation, not just one body. Using the timestamp from the client will be messy - say you get inputs from one client marked time x, rewind and run again. Then another clients inputs arrive also at time x so you could end up running the same timeslice of the simulation for every client.
How about a lock-step simulation, where information about inputs travels to the server and back before clients act on it - if your game can get away with having a response delay of one rtt after clicking the mouse or whatever, I think this is the most straightforward way. The bummer is the 'lock' part :) where everything will stop momentarily when network input is delayed.
I am doing this (based on the "1500 archers" article where clients send input for a 'game turn' instead of stamping a time on inputs) and it works nicely. I have not implemented physics on it yet, but I can't forsee any major difficulty with it (ask me in a few weeks time :). However my game will have inputs coming in at only a click or two every few seconds, and can have a reaction delay of a half-second or so before becoming irritating to the player. If your situation is more of a high speed action-game it might not be good enough.

1500 archers article

Thanks for the advice, but my game is an action game; I don't think lock step would be sufficient.
I just got an idea, though. Maybe I could process client input only every server "tick" -- not when it is received. That way, if I accumulated client input packets from multiple clients before a tick, then during the tick I could rewind to the most in-the-past time, eliminating some of the overlap that I would encounter if I were to process client input the moment I received it.
I don't think I have to rewind the entire gameworld, either; I only have to rewind the relevant rigid bodies, the ones that are close to the players that I am rewinding.

This topic is closed to new replies.

Advertisement