10
\$\begingroup\$

i'm doing a fast paced physics game that is a table hockey. With two mallets and one puck. The game runs on iphone / ipad and i'm doing the multiplayer part through GameCenter.

This is how the network system works. The client wich stars the match, will be settled as the server and the one that accepts the match request is the client.

The 'server' has the physics running and the response is immediate and the client also has their physics running so it looks smooth between messages exchange. What i do as the server, is that i send to the client my puck velocity and my position and the client adjusts his puck velocity/position related to the server to keep it sync. Otherwise the physics desynchronizes and it screws it up.

When the network latency is good, bellow 100ms the results are pretty good, i got a smooth playable game on the client side and the weird behavior are minimum. The problem happens when the lag is around 150 to 200ms. In that case, happens that my client puck already hitted a edge and inverted direction but it receives a delay message from the server and it backs a bit causing a weird feeling to the ball behavior.

I've readed a few things about it:

Pong Network Example

Click Synchronization Example

Wikipedia on Clock Sync

So, how can i solve this? As far as i've read the best option that i have is to do a clock synchronization on the server/client with a timestamp so that when i get delay messages related to my clock, i just ignore then and let the clients simulation do the job. Do you guys agree with that? And since im sending data unreliable (UDP) i may get delayed messages or messages out of order.

If that is the best approach, how do i implement the clock synchronization. I've read the steps on how to but i didn't quite understand it.

It says that:

  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 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 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.
  5. All samples above approximately 1 standard-deviation from the median are discarded and the remaining samples are averaged using an arithmetic mean.

Following this example i would have this:

Lets pretend the game has loaded and my client time is 0 now, so i send to the server that my time is 0.

The messages takes 150ms to get to the server but the server's clock had already started and is 1 second ahead of the client. When the server get the message the time will be: 1.15 and sends that time to client, are we good? Lets pretend our lag is constant at 150ms.

Now the client receives the time 1.15 and subtracts current time from sent time and divides by two to compute latency. Wich is: 0.3 - 0 = 0.3/2 -> 150ms.

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:
Client time: 0.3 Server time 1.15
0.3 - 1.15 = .85 + latency(.15) = 1

How is that synchronized? What am i missing?

It's my first time on multiplayer and network experience, so i'm a bit confused.

Thank you.

\$\endgroup\$
1
  • \$\begingroup\$ Good question. Could you correct: 0.3 - 1.15 to be 1.15 - 0.3 ? \$\endgroup\$
    – Ciaran
    Commented Jan 6, 2012 at 22:55

1 Answer 1

12
\$\begingroup\$

The algorithm posted was correct, but in your example you are forgetting about the time it takes for the server packet to get to the client, so:

Server time: 1
Client time: 0
Client sends 0 to server

... 150ms to get to server  (ping is 300! not 150ms in this case. Ping is round-trip)

Server time: 1.15
Client time: 0.15
Server receives packet and sends client 1.15

... 150ms to get back to client

Server time: 1.30
Client time: 0.30
Client receives 1.15 from server

Now as you can see, if the client changed its clock to 1.15, it would be 0.15 behind the server, this is why you have to adjust for the Ping (aka Round Trip Time [RTT]). Here is the full delta time calculation done over many steps:

Server Time - Current Time + Ping / 2
= Server Time - Current Time + (Current Time - First Packet Time) / 2
= 1.15 (Perceived, not actual!) - 0.30 + (0.30 - 0.00) / 2
= 1.00

This gives us the correct delta time of 1.00 seconds

\$\endgroup\$
11
  • \$\begingroup\$ Im getting it, so my client clock is 1.00 and server is 1.30 After i get i message from the server do i have to add the ping to check if is a late message or something? Another thing, what if the latency changes, do i have to keep doing those calcs all the time? \$\endgroup\$
    – gmemario
    Commented Oct 20, 2011 at 14:47
  • \$\begingroup\$ The delta time of 1.00s is to be added to the current clock to make the client's time equal the server's time. Latency is always changing, each packet will have a slightly different RTT. In a short timeframe like in a game, I would simply do this time sync only once, the client will have a pretty good guess as to what the server's time is and both clocks should be moving ahead at approx the same pace. Only exception would be if you received a packet that appears to be from the future. In that case, there are 2 solutions: 1) Do a new time sync. 2) Advance your clock to match the future clock \$\endgroup\$ Commented Oct 20, 2011 at 15:01
  • \$\begingroup\$ Ok, lets look at this situation just to make sure i got it: Server time: 1s Client time: 0s 150ms to get to the server Server time: 1.15s Client time: 0.15s Server sends client 1.15s 200ms to get to the client So, my ping now is 350ms. Is that correct? Server time: 1.35 Client time: 0.35 Doing the calcs: 1.15 - .35 + (0.35 - 0.00) /2 Now my deltaTime = 0,975 If i add the delta time 0,975 to my .35 i get: 1,325 Wich is kind of desync. Is that correct aswell? \$\endgroup\$
    – gmemario
    Commented Oct 20, 2011 at 15:07
  • \$\begingroup\$ @Gilson, That is correct. If the latency for the two packets is different (almost guaranteed), the client's delta time calculation won't be perfect. There is no way for the client to ever be perfect. In the algorithm you described in the question, the delta time was calculated a number of times and there was a method for selecting and averaging these results. Many time sync methods will do something like this, but they are usually for business critical and long-running servers like for stock exchanges. For the time accuracy you require for a short game, I think that would be overkill. \$\endgroup\$ Commented Oct 20, 2011 at 15:48
  • \$\begingroup\$ @Gilson, As long as the client has a reasonable estimation of the server's time and both clocks move forward at roughly the same rate, you shouldn't notice any issues. When the client or the server sends an action to the other side, they will send their local time. On the receiving side, the message should always be in the past and will need to be interpreted as a past event. This means you need all of the information in the packet, like location, velocity (magnitude+direction) and time. Then you can place the puck there and then, and move the puck from the past to the present. I'm in chat btw \$\endgroup\$ Commented Oct 20, 2011 at 15:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .