Game Networking (2) - Time, Tick, Clock Synchronisation

Daposto
5 min readJul 1, 2020

--

Everyone is talking about time synchronization, however, it isn’t about time at all! It’s about ‘timing’. I initially assumed everyone was talking about system time but after a lot of research that is the worst idea. Using time is a bad idea because clients can manipulate system time and therefore as a server, we can’t rely on it. Something more abstract needs to be used instead. In-game networking we need to know what data, events, packages belong to which frame. It's common to include this timestamp in the packet. So what is it about? It’s about syncing a certain update rate on the client to make sure it sents enough events at the right time for the server-side buffer so that it can correctly predict client movement and world state. I had to search for hours for this information and caused a lot of confusion in my brains.

When a client starts the game, it starts counting from the server state. The intention is to keep the client running at the same speed as the server so that it can deliver input from a client to the server at all times. If you wait long enough and don’t keep up this simulation speed then the client will start to divers from the server. This can be caused by a delay in thread.sleep/latency/lag. It is important to regularly check if the client needs to be adjusted.

Time Sync Algorithm

I haven’t yet implemented the clock-sync my self, so I won’t say too much about it. I found two methods, one from some non-existing site and the other from game dev.net. At last, I found other alternatives in a multiplayer game networking book. I would suggest to read those but also to do a little more research your self.

Method 1

https://web.archive.org/web/20181107022429/http://www.mine-control.com/zack/timesync/timesync.html

The simplest idea is to sync the time between the Client and the Server once (at the beginning of the game session or game event or…) and then rely on both the Client and the Server clock running at pretty much the same speed.

A simple algorithm with these properties is as follows:

  1. Client stamps current local time on a “time request” packet and sends to server
  2. Upon receipt by server, server stamps server-time and returns
  3. Upon receipt by client, client subtracts current time from sent time and divides by two to compute latency. It subtracts current time from server time to determine client-server time delta and adds in the half-latency to get the correct clock delta.(So far this algothim is very similar to SNTP)
  4. The first result should immediately be used to update the clock since it will get the local clock into at least the right ballpark (at least the right timezone!)
  5. The client repeats steps 1 through 3 five or more times, pausing a few seconds each time. Other traffic may be allowed in the interim, but should be minimized for best results
  6. The results of the packet receipts are accumulated and sorted in lowest-latency to highest-latency order. The median latency is determined by picking the mid-point sample from this ordered list.
  7. All samples above approximately 1 standard-deviation from the median are discarded and the remaining samples are averaged using an arithmetic mean.

The only subtlety of this algorithm is that packets above one standard deviation above the median are discarded. The purpose of this is to eliminate packets that were retransmitted by TCP. To visualize this, imagine that a sample of five packets was sent over TCP and there happened to be no retransmission. In this case, the latency histogram will have a single-mode (cluster) centered around the median latency. Now imagine that in another trial, a single packet of the five is retransmitted. The retransmission will cause this one sample to fall far to the right on the latency histogram, on average twice as far away as the median of the primary mode. By simply cutting out all samples that fall more than one standard deviation away from the median, these stray modes are easily eliminated assuming that they do not comprise the bulk of the statistics.

Method 2

  1. When joining a game, have the client send the server a time sync request packet with the client’s current local time.
  2. When the server receives this packet, have the server send back to the client a time sync response packet with the following: a) The local time that the client originally sent to the server b) The server’s current game time.
  3. When the client receives the response packet, he subtracts the local time in the packet, from his current local time. This gives him the round trip ping value.
  4. The client divides the round trip ping by 2 to get an approximation of the one-way latency.
  5. The client then adds the one-way latency that he just calculated to the server’s ping time he received in the packet.
  6. The client sets his game time to this newly calculated time.

PLL

Another algorithm that is directly related to time sync (while being pretty much unused by games103) is the so-called Phase-Locked Loop (PLL). Strictly speaking, PLL doesn’t really synchronize time; what it is doing is creating a clock that is synchronized (both frequency-wise and phase-wise) with an incoming signal (in our case, with packets coming from the Server, as shown on Fig 3.2). However, very often such a clock-synchronized-with-incoming-signal is exactly what we need. This is especially true when speaking about our buffers-on-receipt, as such a clock will answer the question of “when to expect the next packet” in nearly-the-best-possible-way.

Quotation from Development and Deployment of Multiplayer Online Games, Vol. I.

NTP

Another option is to use NTP-like protocol using your Server as a kinda-NTP source. Though, if going this way, do not use real NTP; syncing your Client system-wide time to your Server, instead of just syncing your intra-game time, is not what your players will appreciate.

Also, while NTP as such is known to be very reliable (and addresses both problems of sync-once), implementing full-scale NTP just for game purposes is maybe a bit to overkill.

Quotation from Development and Deployment of Multiplayer Online Games, Vol. I.

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)

Resources

y4pp.wordpress.com

Game Dev Forum:

https://www.gamedev.net/forums/topic/648861-serverclient-time-synchronization/

https://www.gamedev.net/forums/topic/683580-server-client-ticks-lag-compensation-game-state-etc/

https://www.gamedev.net/forums/topic/704579-need-help-understanding-tick-sync-tick-offset/

https://www.gamedev.net/forums/topic/698005-why-keep-client-and-server-ticks-in-sync/

Clock Sync Implementation

https://pastebin.com/EaAK9Fce

https://forum.unity.com/threads/multiplayer-physics-game-where-collisions-between-players-is-the-core.685540/

--

--

Daposto
Daposto

Written by Daposto

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