I'm trying to make a multiplayer platformer game. I can almost get client side prediction and server reconsiliation to work, but there is one issue that I just can't wrap my head around.

Lets say that the following scenario takes place.

  • The server is running at a tick rate of 30 fps.
  • State updates are being sent at a rate of 10 fps.
  • Player movement events are being sent at a tick rate of 30 fps.

The player movement event consists of two fields dx and jump. Which tells the server what directions the player wants to move in. Now lets say the player presses the jump button and then mid-air decides to move sideways. This becomes very problematic as the client starts to move the player instantly. Meanwhile, the server starts to move the player a bit later, due to latently. Eventuelly missing one or two ticks. This leads to gravity pulling the player further downwards on the server before moving sideways, then on the client.

When the server sends the next state update that means the state is massively out of sync because in the servers eyes the player started moving left a bit later then they actually did. Here is a image that describes the situation better:

State description

This problem have kept me up at night, because I can't see a single way the client is going to handle this without ending up the "wrong" position. I've tried multiple forms of client side correction. My most promising solution that still failed were:

  • On the server when receiving a player event. Go back in time to the state that was current when that event was sent. Then reapply every event from that point on the server side. This seems like it would work but didn't for some reason.

This seems like such a fundamental flaw of networked game that I can't understand how ANY networked game works what so ever.

Any help would be very appreciated 🙂

  • \$\begingroup\$ Rewinding to the time of input, applying the input, and re-simulating is indeed the way this is typically solved If your simulation rules are deterministic and your time stamps accurate, then this must produce the same results in the end. If this is not what you observe, then your code has a bug in it, and we'll need to see that code and a detailed repro case / troubleshooting info before we can help you identify and fix that bug. \$\endgroup\$
    – DMGregory
    Commented Aug 10, 2021 at 22:56
  • \$\begingroup\$ Alright, thanks for your response! Then it must have been so that the code is bugged. It is probably the timestamps that are wrong. I suppose there would need to be some time-sync between the client and the server. I've read about the NTP protocol. Is that something you would recommend? \$\endgroup\$ Commented Aug 10, 2021 at 23:21
  • \$\begingroup\$ Since you send inputs at 30 ticks per second, you can effectively just count ticks like turns. Then a client can say "On turn 113, I pressed jump" and the server, who is on turn 115 when it receives that message, knows it needs to rewind two updates then apply that news to the turn-113 state. \$\endgroup\$
    – DMGregory
    Commented Aug 10, 2021 at 23:24
  • \$\begingroup\$ Alright, that seems like it could work. But I'm thinking if the server and client somehow get out of sync, how big of a deal would that be for future state updates? Or is that event still very unlikely. \$\endgroup\$ Commented Aug 10, 2021 at 23:30
  • \$\begingroup\$ If the user's clock drifts by 33 ms relative to the server during a game then you've either been playing a LONG time or one of you is moving at relativistic speeds. \$\endgroup\$
    – DMGregory
    Commented Aug 11, 2021 at 0:02

1 Answer 1


Keep track of unconfirmed inputs (basically an array of the actual state of player's control buttons in each frame) on the client. Upon receiving the game state from the server, put the player back into the position that the server dictates. And now just replay all the inputs that server has not confirmed yet on the client. With this approach you don't need to go back in time on the server. The client simply lags a bit behind the server, but as it always replays its remaining inputs, it effectively hides the lag.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .