0
\$\begingroup\$

I'm building a HTML5 / Websockets based multiplayer canvas game for Facebook and I've been working on the server code for a few days now. While the games pretty simple with a 2d top down, WSAD controls and mouseclick fires a projectile to the cursor x/y - I've never had to do real-time multiplayer before. I've read a few great documents but I'm hoping I can overview my general understanding of the topic and someone can validate the approach and/or point out areas for improvement.

Authoritative multiplayer server, client-side prediction and entity interpolation (and questions below)

  1. Client connects to server
  2. Client syncs time to server
  3. Server has two main update loops:
    • Update the game physics (or game state) on the server at a frequency of 30 per second (tick rate?)
    • Broadcast the game state to all clients at a frequency of 10 per second
  4. Client stores three updates before being allowed to move, this builds up the cache for entity interpolation between update states (old to new with one redundency in case of packet loss)
  5. Upon input from the user, the client sends input commands to server at a frequency of 10 per second - these input commands are time stamped with the clients time
  6. Client moves player on screen as a prediction of what the server will return as the final (authoritative) position of client
  7. Server applies all updates to its physics / state in the previously mentioned update loop
  8. Server sends out time stamped world updates.
  9. Client (if is behind server time && has updates in the queue) linearly interpolates the old position to the new.

Questions

At 1: possibility to use NTP time and sync between the two?

At 5: time stamped? Is the main purpose here to time-stamp each packet

At 7: The input commands that come in will be out of sync per different latencies of the clients. I'm guessing this needs to be sorted before being applied? Or is this overkill?

At 9: is the lerp always a fixed amount? 0.5f for example? Should I be doing something smarter?

Lots of questions I know but any help would be appreciated!!

\$\endgroup\$
1
\$\begingroup\$

At 1: possibility to use NTP time and sync between the two?

Possible but wrong. NTP is not designed for synchronizing as a game needs. You also don't want to synchronize time anyway. You want to synchronize ticks. Time is fuzzy; ticks are clear.

You also don't want to just sync time once. Every packet/message should have a source tick number. Latency should be constantly measured between client and server so that a client can estimate the server's tick (last_tick_received + time_since_last_message / server_tick_rate).

This might even be physics tick rather than game loop tick.

At 5: time stamped? Is the main purpose here to time-stamp each packet

As above, tick-stamped. Actual simulation happens in ticks. Ticks are whole numbers. Time can expand or contract around ticks as process get ahead or behind. Time is wibbly-wobbly. Ticks are absolute.

At 7: The input commands that come in will be out of sync per different latencies of the clients. I'm guessing this needs to be sorted before being applied? Or is this overkill?

This is impossible to solve perfectly.

Ticks help. The second part is to remember that you are constantly measuring/estimating latencies between all clients and server. If a client A and server has a latency of 50 ms then the server knows any message it receives from the client is from 50 ms in the past. If client B and the server has a latency of 100 ms then the client knows that any message it receives from the server is from 100 ms in the past. The server can arbitrate to tell client B that client A moved 50 ms ago, and client B adds its latency to know that client B actually moved 150 ms ago.

At 9: is the lerp always a fixed amount? 0.5f for example? Should I be doing something smarter?

You could use a steering behavior rather than straight lerping. The further out of sync things are, the stronger correction that needs to be applied. A constant LERP function can result in some odd artifacts.

\$\endgroup\$
  • \$\begingroup\$ This is excellent - thank you so much for your answers Sean. Have used a tick rate of 1000/30 and im currently tracking the tx/rx from client to sever to work out the latency, its working really well. At this point I think I'm ready to broadcast update packets to all clients from the server with the world state and use the tick as the id so that when the client reaches the correct tick it will apply the update. Not sure if that's right but it seems like the next step at least :) \$\endgroup\$ – antonmills Sep 1 '16 at 7:14
  • \$\begingroup\$ @antonmills: a more common case is getting updates for ticks in the past. There's heuristics there to determine if the update should be applied, how it should be applied, and how much extrapolation should be done. It's another thing that's impossible to get perfectly right, but you can at least close in on something Good Enough(tm). \$\endgroup\$ – Sean Middleditch Sep 1 '16 at 17:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.