Advertisement

Syncing "Ready Set Go"

Started by July 06, 2006 05:30 AM
10 comments, last by Void 18 years, 6 months ago
Hi I'm developing an multiplayer (8 person max) RTS, and looking at ways to sync the game. The game loop will be lockstep as described in gamasutra AOE article http://www.gamasutra.com/features/20010322/terrano_01.htm , update loop running at 15fps, and the packets will be sent every 3 frame (each game turn is 200ms). The client commands are sent to server and executed a few (2) frames later, and sent via TCP (or guaranteed UDP), as described in forum FAQ. I will use either Raknet or HawkNL as the network library. What I couldn't find good info is on how to sync the game start and loop. Let's say the game will start in a lobby system, server creates the game, and waits for clients to join. When there are enough connected clients, server will press the "Let's go" game button, and they need to sync the game start. This is something I have in mind. An timeline diagram when server presses "Start" TimeLine-> Server 1. 3. 4. -------------------- Client 2. 3. Event 1. Server sends a "Start in 1 sec" packet and timestamps it. 2. Client receives "Start in 1 sec" packet. Client subtract the latency to its 1 sec countdown (Raknet provides getting the lag) 3. Both start the game. Client send a timestamped "Started" packet to server. 4. Server receives client "Started" timestamp packet. We can use this to check if (timestamp at 1. - lag) is 1 sec, or else it means client is out of sync. In the game loop, server will broadcast commands to all clients to be executed 6 frames (2 game turn update) later. If server/clients do not send/receive the broadcast message, then they will pause (ideally a messagebox pops up to wait) There are a few problems I foresee though - Game lag is restricted to 2 update cycles (400ms). If the lag is bad, then the messagebox keeps popping up - after syncing the game start, we let each machine run the update loop 15fps. Ideally, we should timestamp the broadcast message and use it to sync. So every broadcast message, server will send, "I'm at frame XXX". If the client frame is slower, then it will ignore and catch up. But what happens if the server is the lagging one? I like to hear how you guys are doing the sync.
Why do you need to worry about syncing if it's running lockstep?
Advertisement
We need get the server started in sync in order for lockstep to work, no?
I thought you said the server starts up first and waits for the clients to join. For a lockstep setup, you can consider every 'turn' to be a sync.
Quote:
When there are enough connected clients, server will press the "Let's go" game button
This equates to the server sending out a message saying "Hey everybody the game has started and it's now turn 1, so give me your inputs for turn 3" (turn 3 if you are doing the 'pipeline' style messaging as the article describes). Until each client has provided inputs for turn 3, the game goes nowhere. When the necessary inputs arrive the simulation continues - in sync!

I am using a system very similar to the article, this is how I manage game startup.

1. Clients click 'Join' in lobby and are added to a game stub.
2. When the stub has enough players, the server loads the game data, starts the simulation, then tells clients to start loading the data too.
3. When a client finishes loading game data, it sends a join game request and is added to the game. Upon joining, the server makes one empty input for it because the client will never send an input for turn n+1 (since it always sends inputs for turn n+2)
4. While waiting for other clients to join the game, clients who have already joined send their inputs in order to keep the lockstep simulation happy, but these inputs are not actually applied to the game world.
5. When the last client joins, the server notifies clients that the game has started, and starts using their inputs.

This is a strictly client/server only arrangement though, I doubt it would be so straightforward if you want the 'star shaped' peer to peer arrangement. In practise, this finds most clients joining the game around 10-15 turns after the simulation has started running, depending on how fast they can load the game data. That's ok because in my game it doesn't matter if the game world runs for a little bit before the clients are present, but your situation may differ - say if you want a scripted convoy moving across the map which should get to the other side in exactly 2 minutes - you will have to send a 'reset world' input message when the last client arrives to make sure everything is the same.
Thanks for the long reply zppz. Your setup is the same as what I needed. You explain it very cleary, I know how it works :)

So you do not sync the timers beyond the starting packet. I just wondering if its a concern cos clocks may be wander off by miliseconds over the long run, or am I over worrying?
You measure game time in game turns. The server gives you the "go ahead" to enter each new game turn. Thus, it doesn't matter whether the clocks sync up -- the turn number is updated through the network packet.

For display, you typically run a frame rate faster than the game rate. There, you display animations based on the local time, but because those are just eye candy (local animations), syncing the clock for animations between computers doesn't matter, as long as the units are in the right place at the right game turn.
enum Bool { True, False, FileNotFound };
Advertisement
Quote:
Original post by hplus0603
You measure game time in game turns. The server gives you the "go ahead" to enter each new game turn. Thus, it doesn't matter whether the clocks sync up -- the turn number is updated through the network packet.


Hmm.. that's getting me confused again. When the client receives a turn packet, it already means the the turn has executed on server, and the packet contains the input processing for next turn+2 event.

Every client should try to catchtp their update loop to this packet (if their loop slows because of graphics). If the network lag doesn't exceed two turns, then the game doesn't get interrupted. Else server will have to wait for input packet from this client by pausing the game. This would mean the client is trying to sync their clock with server, no? As I see, clients must be sync cos they should execute the same turn at the same time (as close as possible).
The sync is implicit in the "next turn" packets. Yes, those packets will set the pace of the game.

In a typical set-up, you will queue commands when the user makes then, and when you receive the "turn" packet, you will send all the queued commands, and then start a new queue. That way, you don't need a clock on the client at all (except for animation).
enum Bool { True, False, FileNotFound };
Wouldn't each player receive the turn packet at different times because of different lag to server? Client needs the server timestamp to know when the turn packet actually took place (calculated using roundtrip time), so some sort of sync is needed, no?
All the clients (and the server) need is the turn number. The sync within the turn doesn't matter. This assumes that all actions (movement, attack, etc) are resolved on each turn (pulse). The clients are not perfectly in sync, but they agree on what turn they issue commands for, which is all you need.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement