Game Networking (9) — Bonus, Overwatch Model

Overwatch uses a command model. This article will put all the previous articles together into this model. There are many other models, and this is not the only way of going about game networking. If you want to see the original talk you can head over here. However, this article has combined the information from multiple sources and tries to bring up some extra details.

Before diving into this model I want to quickly elaborate on the event-based networking approach. The main concept of this approach is that the client hasn't any client-side authority. All changes are monitored by the server. The server will have authority. This is accomplished by sending commands/events. I in this overwatch model it is called command and so will I call it.

A ‘command’ is an instruction that occurs at a certain ‘command frame’ and is sent from the client to the server.

The following diagram is SOO clear about how this whole syncing works. It’s from the overwatch GCD talk.

overwatch-gcd slide

In this diagram you see a server and client running at the same command frame rate, the client will always run ahead of the server, because it is the client who presses the buttons and contains the newest data. In order for the client to send an update for command frame 9 on the server, it has to send it on command frame 15 locally. The reason for this is that the client is removed ‘half an RTT’ (latency) away from the server.

Now take the following diagram:

The above diagram illustrates us the server responding with an authoritative update (player image). The authoritative update has to travel ‘half the rtt’ back to the client. Therefore the time between an event from the client until the server acknowledgment is a full round trip + the buffer (we are going to talk about just in a bit). From the start of the round trip until the current command frame the client is predicting its states unsupervised. This is a problem because if the client is off in it’s a calculation the server will correct it but the client will experience some snap back to the server state. Because of this reason we want to have the client run just enough ahead of the server so that if it sents an update it arrives just on time (1–2 ticks).

The RTT time changes and fluctuates between some values. To establish the RTT you’ll first have to do some round trips from client-to-server. The RTT will eventually smooth out and establish a certain value.

Because the latency fluctuates, the client its event sending time, simulation time, command frame speed needs to be adjusted at runtime so that it delivers the event for the server just-on-time, not to fast, not to late. This is called time synchronization!

So about that buffer, it should stay small. Because more events would mean that the client fires of more events then needed and is running faster then the server does. As discussed this should not happen. We need to keep the client as close to the server command frame in order for the client it’s prediction to work correctly. This buffer will generally have 1–3 events.

The magic of time synchronization happens on the client. The following actions are performed to guarantee that the client is always on time with its events.

  • If the server receives an event for a tick that’s already executed on the server, tell the client that it’s too far behind and should increase its estimate of transmission latency (add more to the clock to get estimated arrived server clock.)
  • If the server receives an event with a (tick, _) that is ludicrously far into the future (more than you’re willing to de-jitter-buffer for this connection) then the server should tell the client to reduce compensation (shift clock backward.)
  • If the server receives more commands when there’s already more than one queued command (for some value of “one”) then you can tell the client that it’s running ahead, and should adjust its estimate backward a bit.

The following algorithm can be used to shift the clock for and backward:

  • Each time the client is more than 32 ticks off, adjust by one-quarter the amount in the appropriate direction.
  • Each time the client is more than 15 ticks off but less than 33, adjust by one-eighth the amount in the appropriate direction.
  • Each time the client is late by 0 to 15 ticks adjust backward by one tick.
  • Each time client is early by 1 to 7 ticks, leave it be. (Or some other value for “7” for how much jitter compensation you’re prepared to accept.)
  • Each time the client is early by 8 to 15 ticks, adjust forward by one tick.

Heavy Lag

So the buffer should not be big, the client should not run too far ahead, and the timing for client events should be just on time. What if a single packet drops? We don’t have any packets to run the server simulation on. This is dangerous because the server has to assume the client state and will send this in an authoritative state update.

As you can see in the above diagram the packet with the exclamation mark is assumed by the server. Some packet from the client got lost. This is a problem we can’t just make the client sent more and we can’t let the client simulate further than really needed so that will cause inconsistencies on the client prediction. What we can do is sent a sliding window of past events from the client to the server. About ~10 command frames into the past. The size of this single packet won’t be very big because it probably contains the same events (like when pressing W). This can easily be compressed into a smaller packet. Regarding the previous system (sending 1 event), this system will be able to, if a packet drops, get the missing event from the next packet.

Some other info

  • If you want the simulation to be consistent, then the client and server need to run SIMULATION at the same rates. Rendering doesn’t need to be run at the same rate as simulation.
  • There will be one or two round-trips when first establishing the connection where the server lets the client know its current tick, then the client tells the server what the server tick received was, and then the server tells the client what the effective round-trip latency seems to be based on that, after which point the client can start assuming it knows the server tick. When the server sees a command that is way too early or too late, it can tell the client to adjust in the appropriate direction.
  • Estimated latency doesn’t affect how often you send packets, it mainly affects the clock offset between server and client. It also typically affects how far into the future you forward extrapolate displayed entities, if you choose that option.
  • With clock syncing, you can throw away events that arrive too late but keep the ones that still have time to execute.

End

And that was it. There are many factors in getting this model to work. Simulating the command frames at the right speed. Calculating the RTT in order to know what speed to run. Let the server tell the client regularly what the client its offset is with the server and adjust the simulation speed if necessary. Sending authoritative updates, implementing client-side prediction. However, if done right, it provides a solid system that can adjust to networking pressure, latency, quick speeds, easy snapshots, less cheating. I highly recommend watching the original talk a couple of times. I wish you good luck ;).

part 0 (intro)
part 1 (Interval and ticks)
part 2 (Time, Tick, Clock Synchronisation)
part 3 (RTT, PING, latency, lag)
part 4 (Client-Side Extrapolation a.k.a. Dead Reckoning/ Interpolation)
part 5 (Compression, delta encoding, interest management, bit packing)
part 6 (Event, Input, Command Ring/Buffer/priority/Queue)
part 7 (Deterministic vs State)
part 8 (Present, past future where am I)
part 9 (Bonus, Overwatch Model)

--

--

--

Programmer, problem solver, learning everyday. I write about anything mainly to straighten my own thoughts.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Troubleshooting applications in Linux

Terra Station wallet (desktop app) are not safe? Rude developer’s response.

Dealing With Code Performance — Micro changes and Macro Optimizations

API vs RESTAPI

How To Get The Flight Status Of Air North With An API

How to create your own custom URL shortener in 10 minutes for free & deploy to GitHub 🚀

Is There Any Free API To Request Metal Rates?

Your Software Development Team Will Benefit From These 4 Things

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Timon Post

Timon Post

Programmer, problem solver, learning everyday. I write about anything mainly to straighten my own thoughts.

More from Medium

Unity UI Scroll View — How to Make It Work

Programming Diaries — Day 3 — Overflowing with information…

Benefits of Prototyping without Assets

Unity3D Fundamentals