This is a sample implementation of a client-server architecture demonstrating the main concepts explained in my Fast-Paced Multiplayer series of articles. It won’t make much sense unless you’ve read the articles first.
Although it’s not production-quality code, you may use this code in your own applications. Credit is appreciated although not required.
The views above show the state of the game world according to the server, and what two clients are rendering. You can move the blue ball, controlled by Player 1, with the LEFT and RIGHT arrow keys; and the red ball, controlled by Player 2, with the A and D keys.
Move the blue ball. There’s considerable delay between pressing the arrow keys and the blue ball actually moving. Without client-side prediction, the client only renders the new position of the ball only after a round-trip to the server. Because of the 250ms lag, this takes a while.
Set the player 1 Lag to 0ms, and try again. Now the client and the server move in sync because there’s no delay between them, but the movement isn’t smooth, because the server only updates its internal state 3 times per second. If you increase the update rate of the server to 60, we get smooth movement.
But this is not a very realistic scenario. Set the player 1 lag back to 250ms, and the server update rate back to 3. This is closer to the awful conditions where a real game still needs to work.
Client-side prediction and server reconciliation to the rescue! Enable both of them for Player 1 and move the blue ball. Now the movement is very smooth, and there’s no perceptible delay between pressing the arrow keys and moving the ball.
This still works if you make the conditions even worse - try setting the player 1 lag to 500ms and the server update rate to 1.
Now things look fantastic for player 1’s own entity, the blue ball. However, player 2’s view of this same entity looks terrible. Because the low update rate of the server, player 2 only gets a new position for player 1’s entity once per second, so the movement is very jumpy.
Enabling client-side prediction and server reconciliation for player 2 do nothing to smooth the movement of the blue ball, because these techniques only affect how a player renders its own entity. It does make a difference if you move the red ball, but now we have the same jumpiness in player 1’s view.
To solve this, we use entity interpolation. Enable entity interpolation for player 2 and move the blue ball. Now it moves smoothly, but is always rendered “in the past” compared to player 1 and to the server.
You may notice the speed of the interpolated entities may vary. This is an artifact of the interpolation, caused by setting the server update rate too low in relationship with the speeds. This effect should disappear almost entirely if you set the server update rate to 10, which is still pretty low.
Client-Side Prediction and Server Reconciliation are very powerful techniques to make multiplayer games feel responsive even under extremely bad network conditions. Therefore, they are a fundamental part of almost any client/server multiplayer network architecture.