Take the 2-minute tour ×

I've read Valve + Gafferon and hundreds of pages from Google, but for whatever reason I can't get my head around client prediction.

To my understanding, the basic problem is:

  • Client A sends input at T0
  • Server receives input at T1
  • All clients receive the change at T2

At T2 however, using client prediction, Client A is now at a position appropriate to T4.

How do you ensure that the Client A, when predicting that the server will accept the movement request, won't be ahead of the server? Obviously all the time they are ahead, this results in snapping back to where the server last saw them. With all corrections I've tried, this is still noticeable when you stop, because the server stops behind you

share|improve this question

3 Answers 3

up vote 17 down vote accepted

I wrote a series of articles on this. It is based on the same ideas you've read elsewhere, but explained in a very detailed and (I hope) accessible way.

share|improve this answer
Excellent articles :-) I'd love to see the fourth part of the series. As a small suggestion, a link to the next part at the end of each of the articles would certainly improve navigation. –  O. R. Mapper Jul 11 '13 at 19:09
Thanks for the suggestion and your kind words :) –  ggambett Jul 12 '13 at 11:54
@O.R.Mapper - I finally wrote the 4th article! gabrielgambetta.com/fpm4.html –  ggambett Jul 30 '13 at 16:15
Kudos for your article series :-) Very helpful, thanks :-) –  O. R. Mapper Jul 31 '13 at 20:33
All articles (I could find) that talk about reconstructing past using stored snapshots take shooting as example. Does this apply for movement as well? I can imagine that movement resimulation can lead to some big differences for other players if they can collide with each other. Let's say two players move against each other and one of them stops moving few "steps" away from would be collision point. This stop commands arrives late because of lag so if we resimulate world, the two players would be in very different positions –  Lope Nov 6 '13 at 22:10

I haven't actually implemented this (so there might be some problems I'm not immediately seeing), but I thought I'd try to help.

Here's what you said is happening:

Client A sends input at T0

Server receives input at T1

All clients receive the change at T2


It probably would be useful to think in terms of server time. Its (probably) very similar to how interpolation works.

Every command is sent up with a server time. This server time is figured out at the start of a match by querying for the server tick, compensating for ping time. On the client you have your own local tick count, and each command you send up is converted to server ticks (it's a simple subtraction operation)

Also, the client is always rendering "in the past". So you assume that the world the client sees is, say, 100ms behind what the server's time really is.

So let's rephrase your example with server time (designated by S).

Client sends input at T0 with server time S0 (which I'm guessing is really "client representation of server time minus interpolation time"). Client doesn't wait for response from server and moves immediately.

Server receives input at T1. Server figures out client's authoritative position at server time S0 given by the client. Sends that to the client.

Client receives the authoritative position at T2 (still with designation of server time S0). The client keeps track of some past amount of time worth of previous events (probably just a queue of all unconfirmed predictions).

If the predicted position/velocity/whatever that the server sends back at S0 is different than what the client has stored at S0, the client handles this somehow. Either by snapping the player back to their past position, or resimulating the previous input, or maybe something else I haven't thought of.

share|improve this answer
That's all correct except the bit about the client rendering in the past. Relative to the server, the client is actually rendering in the future! The server knows that the information it has from each client is old and that each client will have already changed since then. –  Kylotan Jan 16 '12 at 0:37

Client A is always ahead of the server - but it doesn't matter. You only have to snap the client back if the server says there was a problem with the reported position, at which point the client re-runs all the changes it has made since the error with the corrected values, to bring it to a state compatible with the server.

To do this, the client needs to remember some of its past state and past updates. This may only be a few simple values such as position, velocity, orientation, that sort of thing. The server will periodically send an acknowledgement that various client updates were legit, meaning they can now be forgotten from the client. If the server however reports that an update was invalid, the client state rolls back to that point and the future changes are applied to that modified state.

There are some extra links at the bottom of the Valve article that are worth reading - this is one of them: https://developer.valvesoftware.com/wiki/Prediction

share|improve this answer
So, am I right in thinking that client (at t=4) receives info about t=2, so it resets state to t=2 then re-runs updates to bring objects from t=2 to t=4? –  George Duckett Jan 15 '12 at 13:15
I'm still not grasping it for some reason. The server isn't being told the position of the player, only the inputs. So the player is moving from the last position that the server said it was at. Input is applied. Server is informed. Server confirms input to everyone. Assuming all commands are accepted, the server will still be behind Client A - so when Client A stops, its character will stop immediately then slide back to the servers location when it receives the stop confirmation. –  Chris Evans Jan 15 '12 at 13:42
@GeorgeDuckett: yes (although it doesn't have to be t=4, it could be whenever a discrepancy is detected, and there could be any number of re-applied updates.) –  Kylotan Jan 15 '12 at 16:35
@ChrisEvans: known state + changes based on input are equivalent to sending state anyway. As for the stopping example, that in itself is an input, and the server is still simulating movement until it receives that input. Assuming constant latency, the server will stop the player moving at precisely the same position that the client saw when he stopped moving, because the client was ahead of the server. (In the real world, the latency varies, so you interpolate a bit to smooth it out.) –  Kylotan Jan 15 '12 at 16:41

Your Answer


