Fast multiplayer client/server demo

Fork me on GitHub

Clone of Gabriel Gambetta's original demo, adding entity interpolation. I made this in order to better understand the original, and to learn about developing TypeScript projects. Gabriel's series of articles explaining Fast-Paced Multiplayer games is an excellent read, and essential to understanding this.

Disclaimer: I'm not a game developer, and this is the first gamey thing I've tried, so beware of the code.

Writeup below with more on what to do with this page.


Game views

Player 1 (move with: q, e)

/ / /
Non-ackd inputs: 0

Player 2 (move with: a, d)

/ / /
Non-ackd inputs: 0

Player 3 (move with: z, c)

/ / /
Non-ackd inputs: 0

Server (authoritative state)


Things to try

With default settings, move player 3 around. Note how smoothly player 3's view renders. Now move player 1 or player 2 the same way and note how slow or jumpy their views update. This shows the effect of client prediction and input reconciliation. (Same as Gabriel's original demo.)

Now observe player 3's view as you move player 1 & 2 around. Note how players 1 and 2 move smoothly -- but delayed -- in player 3's view compared to everyone else's view. This is entity interpolation (EI) at work.

Turn EI on for all players, but give player 1 and 2 very different lag values (say 2000 ms, and 20ms). Then move player 3 around and observe how the other players see the state of the world. Note how the high-lag player's view of the world is considerably delayed, but still smooth.

Check out the recommendations for things to try in the original demo.

TODO: add something to demonstrate lag compensation, the remaining concept from the article series that is not demonstrated.

What's with the weird "easing" when EI is on and server update frequency is small?

I thought this was a bug at first, but it's working as designed. It's a limitation of our naive interpolation function and world state. When world state updates only arrive very infrequently, like once a second, players using EI assume a past movement occurred at uniform speed over the entire time between world states. For example, assume the server sends world states updates every second, and player 3 is using EI. If player 1, e.g., moves a tiny bit over 100ms and then stops, player 3 will see that tiny movement in world state updates that are one second apart, and our interpolation function will drag out the tiny movement over a period of one second instead of 100 ms. If you set the server update rate to be something slightly more aggressive, like 5 times a second, this effect is much less noticeable. At 20 times a second it's invisible. Another fix would be to send a more detailed world state that includes where the player was every 10 ms or something. (This is mentioned in the original articles, but I had to learn the hard way, as usual.)