I'm working on a multiplayer game which involves a huge amount of predictable AI enemies, and a few other players. The enemies are the most important to be accurate, because the game involves pixel perfect dodging.

In deciding how to network this game, there are two main objectives:

  • Smallest possible bandwidth usage.
  • Game remains playable over bad connections, like wifi & mobile.

I have thought of this system:

  • On connection, send full server state to client.
  • Client & server both simulate all enemies.
  • Server sends updates on what tick it is currently on, and anything that's non-predictable (other player movement, etc), but does not include the enemy details.
  • Ensure simulation is deterministic by sharing implementation, using fixed timestep, share random seed, etc.
  • If client gets out of sync, can re-sync by requesting all information again. Can check via tick number or via some checksumming mechanism.

The problem:

How to deal with clients & servers going out of sync due to tick rate discrepancies?

Normally I'd use a delta based on the last tick for the simulation, but the need for a fixed timestep (to avoid floating point error) means that's impossible. If the client or server is running slightly slow or fast, it'll get more and more out of sync. If the sync gets bad enough, we can re-sync.

My basic testing with a Chrome client shows that skew can happen fast and consistently, getting about a tick out of sync every second (at 30fps). Even 1 or 2 ticks off can really ruin the game experience since it's a pixel perfect avoidance game. It seems we'd need to resync every second or so, which may also be jumpy and look weird, though interpolation could smooth it out.

Is my system fundamentally flawed, or is this something that can realistically be smoothed out?

  • \$\begingroup\$ How are you getting so many ticks out of sync so quickly? It sounds like you have a serious error in your game loop. Ordinary clocks should be accurate enough to stay synched for the expected length of a player's game session. \$\endgroup\$
    – DMGregory
    Jan 3, 2019 at 12:52
  • 1
    \$\begingroup\$ Are you counting each "tick" as one rendered frame in your main loop, or as a time interval measured from the system clock? Only the system clock will work, client rendering will be different for everyone's hardware setup. \$\endgroup\$ Jan 3, 2019 at 18:01


You must log in to answer this question.