What do you mean "don't measure time with secs/milisecs, instead use ticks" for state synchronization?

Started by
4 comments, last by hplus0603 10 years, 3 months ago

Hmm from what I read here in this forum section, it is highly discouraged to measure time using seconds/miliseconds, instead use ticks for synchronization. I wonder what does it really mean, since synchronization involves ping time, and it is measured with miliseconds. I recently read the valve network synchronization technique, however I cannot seem to fully grasp it as a whole.

https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

From what I can swallow of those huge wall of texts, I think this is how it was implemented.

1. When the game start, the server sends me the "Tick number" (assume it's 0). The server increase this number every time it do simulation update.

2. I receive it. I, too will increase this number every local simulation update.

3. Assume the server and client update rate is 10 fps, which is 100 ms between each tick. Between those tick I collect user input, and of course I include the current tick number. Of course I do read packets from server, but let's not focus on that. The server is doing almost the same thing on his side (read, simulate, send) every 100 ms.

4. Assume it's 100 ms since last tick. Now it's time to update. Me (client), simulate locally using those buffered input. Then directly I send those buffered input to server.

5. Server receives it, perhaps 200 ms later. It reads the client input. However, it must be too late. The server's tick number will almost always be bigger than the client. In server, the tick number currently could be 12, while the tick number included in client packet was 10.

Now, I got several questions :

1. Well, now that there's unmatching tick number, what should the server do? I got the notion that there should be some kind of "rewind and replay" stuffs. But who does it? the server or the client?

2. Assume that at the client's step no. 3, the client press forward and quickly press left. Since this is UDP, I'm sure the packets could be received by the server not in order. Should the client be using reliable/ordered send for input?

Thanks before, I'm trying to make a multiplayer pong, so it's quite relevant. Pong is kinda twitch based, don't you agree ;)

Advertisement

synchronization involves ping time, and it is measured with miliseconds


The *simulation time* should be measured in ticks. That way, everybody runs the same simulation, ticking at the same rate, so that time-variant behavior (like acceleration) is the same across all players.
*real time* of course is measured in seconds, so at some level, there is code that "looks at the clock" and decides what the current simulation tick "should be" and ticks the simulation forward, one tick at a time, until it is.

You can calculate the current target tick as such:

targetTick = (systemTime() - timeOfCalibration) * speedOfSimulation + tickAtCalibration;
None of your simulation code should use "real time," because doing so makes it impossible to unit test, makes it impossible to rewind time if needed, and generally causes bugs.

Well, now that there's unmatching tick number, what should the server do?


In Source, the server may rewind time and re-play the particular entity that provided late input data, as long as the rewind is "not too far." If the rewind is too far, the server must discard the input. The client will somehow detect/be told that it is out of sync and "snap" if that happens.

Should the client be using reliable/ordered send for input?


If your simulation absolutely requires determinism (such as for an RTS or other lockstep game where state is never sent, only inputs,) then yes, you will need reliable, ordered, delivery of commands/inputs. This means the game may stall if one player is having connection issues.
If the simulation can recover from de-sync ("correct" a client) then it's more likely that the rare case of input loss is dealt with by correcting the client whose packet didn't make it.
Typically, each input message will have a timestamp for the simulation tick it was intended for. As long as the server sorts the messages by tick, and/or rewinds time the right amount for each, then things will work out.
enum Bool { True, False, FileNotFound };

Hmm I don't think I get it here. I feel so stupid. I understand what a tick rate is, and that is used for fixed time-step which helps ensuring predictability also to stabilize physics. I know it means to decouple physics and rendering. Also, now I get that pingtime is used for that rewind and replay stuff, also for client side prediction. Now to clear another confusion.

1. Based on the approach above, of course the tick number in the server and the client will differ (because of lag).

(the server is simulating tick 12, client was sending tick 10) --> (server rewinds and replay, he simulates that client move since tick 10(past) until tick 12(now)) --> (server sends update, telling this is your position at tick 12) CMIIW --> (???)

-should the server informs that it is currently tick 12? I guess so, the server tells the client "this is your state at (current )tick 12". please CMIIW

-should the client update its tick number so it's 12? or continually update his local tick, but use the informed server tick for interpolation? anyway, what should the client do now that it knows the server is at tick 12? of course by this time the client tick time would have changed, perhaps below, equal, or above 12.

-what does it mean that player is ahead of server, behind server? I used to hear this a lot in conversations and forums. I don't get it. But I think here's what it means. Please correct me if I am wrong:

-1. client is ahead of server, if he receives update from server telling "this is your state at tick 12", while locally he is at tick 13 (anything > 12)

-2. client is behind server, if he receives update from server telling "this is your state at tick 12", while locally he is at tick 11 (anything < 12)

-3. client is equal to server, if he receives update from server telling "this is yout state at tick 12", while locally he is at tick 12 too.

The ahead/behind server description you talk about would not surprise me. Note that there is no well-defined, single, language used for these things. For example, a client can be said to be "behind server" even when in the case of 2 in your list, and case 3 could "never happen" because the client would jump forward to the received time stamp in that case.

However, one thing that confuses me is your use of the words "is at tick." You cannot know exactly what tick someone "is at." You can only know what their tick number was when they sent a message. For the client and server to keep their tick rates (rate of tick advancement) in sync, it may be useful for the client to attach its current tick number to packets sent to server, and for the server to return two pieces of data: "When I received a packet that you sent when you were at tick A, I was at tick B. When I sent this return packet, I was at tick C." The client can then look at what its tick is when it receives that packet, and calculate (D-A,) subtract (C-B,) and divide by two; that's the estimated one-way transmission latency. You can also use this information to predict what the tick number will be on the server when the packet you send at tick E actually arrives.

How you then put together these pieces, depends on your specific game model. Source is different from Quake is different from Starcraft is different from World of Warcraft is different from ...

enum Bool { True, False, FileNotFound };

It might be better in future to use some other term that 'ticks' which is the same term used for that crude time system used on various operating systems. Ive never used them ('ticks') except on Sleep() commands and only for very loose code). I may have even changed the tick rate in one usage.

When I saw the last mention in some post with someone being told to use 'ticks' I automatically though of that, and NOT of the method of using an artificial/arbitrary time system (Ive used the high performance/precision timers in my networking many times including for in-line profiling performance)

--------------------------------------------[size="1"]Ratings are Opinion, not Fact

When we say "ticks" on the networking forum, we mean "simulation steps." If you instead think of of ticks as "jiffies," then I can see how that would be confusing :-)

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement