Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm developing an RTS game and I want to add multiplayer support to my game.

I picked the easiest technique to implement for start frame locking technique.

  1. I used server client networking architecture (I think it's my first mistake I think using peer to peer is a better one for this)
  2. On game update every clients send their commands and maybe receive some command then render the frame and wait for all clients to send their update complete message then all of them can go for the next frame.

I send commands and all logic is calculated on the clients based on commands but the clients can go out of sync easily. Every AI controlled units make different decisions on each clients

What I have to do to sync my game? Do you suggest me a better network architecture or technique?

share|improve this question
1  
If your AI is making different descisions on different computers it means your AI is not deterministic. Thats bad. In this case, either your server has to control the AI, or you have to make your code deterministic. This starts from all the players having the same seed, and ends with making sure that : a + b / c gives the same reult on all (target) computers. This can be done as simply as using ints everywhere ;) –  Jonathan Connell Oct 7 '12 at 10:43

3 Answers 3

Games like Megaglest use TCP networking for multiplayer.

It may be that all your players are using the same compiler on the same OS on the same hardware; but more generally, you have to use a portable math library e.g. streflop. You have to use a pseudo-random number generator and specify the initial seed for it. If you use streflop and, say, streflop's Mersene Twister for all game-related actions then your game is deterministic across all clients.

My Ludum Dare 24 game Cage Flight uses TCP sockets and illustrates the poor user experience naked lock-step. What you really need is prediction and correction. There is a nice intro series here.

share|improve this answer
    
+1 for synchronizing seeds of random functions –  Markus von Broady Oct 8 '12 at 15:24

Use sockets, send every action immediately through them. You will save bandwidth for sending only actions instead of lots of information about state of units, and this will also proof the game against hacking.

As Jonathan Connell said, your algorithms must be deterministic, however I don't think not using ints is the issue. If you're rounding a float number into an int, assuming both players use same clients compiled in same language, these numbers should be rounded in same way. But if you use randomizing functions, or if you give different input to deterministic functions, then obviously there's a big chance you will get a different output, and thus, desynchronization.

Now, server should response to you and send same info to another player, with:

  • confirmation that the command (there could be a command's ID) was sent successfully
  • timestamp of when the command was processed
  • information the client couldn't know, e.g. what damage was randomized on server

Or it could also wait for it's simulation 'tick', summarize all changes and then send the summary to both players.

So in example:

  1. Player A selects a tank and orders it to go into fog of war, coordinates X:100, Y:215. This command is sent immediately.
  2. Server calculates path for the tank (client can't do this because of the fog)
  3. TICK! Server sends part of the path to Player A (with timestamp), and nothing to Player B, as this part is in Player B's fog of war.
  4. Player A's client starts to move the tank (after about 100-200 ms)
  5. Player A selects a ship and orders it to go onto Player's B waters. I assume both players see whole water on map, so player A sees this part of the map, and so the path is calculated on client and sent to the server.
  6. Player B selects a building and starts to build an airplane. And sends it to the server.
  7. TICK! Server sends to Player B a timestamp when exactly he started to build the plane, plus path of the ship, and to player A also timestamp and confirmation the path is valid.
  8. Both players see the ship started to move, and player B also sees his airplane's progress bar finally moved.

That's easy. The problem is, it's very annoying to see your units respond even 200 ms after your click. That's why you should try to predict what will happen. It's easiest to explain on point 6:

  • player B selects a building and starts to build an airplane at 11:50:12.530
  • player B sends data to Server
  • time to build an airplane is 20 seconds, therefore the plane should be finished at 11:50:32.530
  • player B knows average ping to server is 170 ms, therefore it offsets end of airplane construction to 11:50:12.530 + (170/2) = 11:50:12.615
  • player B starts to update airplane's progress bar, knowing the construction will take 20 085 ms, and so filling 1% of the bar per 200.85 ms.
  • Server gets the command at 11:50:12.620, and sends back confirmation with such timestamp
  • at 11:50:12.720 player B gets the confirmation of timestamp being 11:50:12.620.
  • player B (or rather it's client) now knows he estimated the time wrong, and has to smoothly transition from it's prediction to the true result.
  • in this case it's save to go for maximum smoothness of the transition
  • so far 190 ms have elapsed. This means progress bar is filled with (190/200.85)% = 0.95%.
  • There are 19 895 ms left to make 99.05% of the plane. That means since now, filling every next 1% of the bar will take 19 895 / 99.05 = 200.86 ms.
  • (I know the difference is almost none here, but it's only an example, and would make more sense with a severe lag)
  • so now progress is calculated as 0.95% + time_from_server_response / 19 895 * 100%
  • if the airplane has some rally point, it's movement will be synchronized with server (if server knows the rally point), because calculating his movement will have same, synchronized input - end of it's construction.
share|improve this answer
    
Yeah, this is pretty much what I was going for.. –  Zehelvion Oct 7 '12 at 16:14

Jonathan Connell felt I did not support my case against Frame Locking well in the original answer and while it is a subjective matter, I believe I can present objective advantages in using an alternative technique to frame locking. While we all agree it could work for your game. It is by no means definitely the best or only was to achieve what you are are working to create.

So hear me out:

Minimizing lag in a RTS

RTS and action games are not the same animal. In fps, you constantly transfer tiny precise movements to the server. RTS need to manage armies, sometimes hundreds of units where each unit needs to do path-finding, auto-attack(be aware of environment) and that means the units are somewhat independent. That is why people came up with Event-Locking.

With frame locking, the client sens an update every frame with the user's input. The sever processes input and replies with the result of all moves made by the players. This method is great for low latency networks like home networks if you play with your friends through wifi without using the Internet. This does not do wonders when you play online and there is latency, especially if your server is not ideal for multi-player gaming. This is without mentioning that the real world is not ideal, maybe one of the players is using a torrent client that is slowing the connectivity and causing additional latency and packet loss. Maybe another player has a poor connection, using a cellular device to play the game? Nobody knows what could happen during a network game online. That is why the system has to be as foolproof as possible. That is why I do not recommend frame-locking personally.

If all the clients send updates at the same pace things will work. What happens if an update is not received due to networking issues? The server and the rest of the clients need to 'freeze' and wait for that update. If the server and the other clients proceed the game will not be synchronized which is what we are working to prevent.

Depending on your game architecture, the player could see the results of her actions. What about the rest of the players, the packet did not make it, they do not see it.

You can adjust the system to compensate by adapting to the communication lag. This will make the system less responsive when there is a little more lag.

We need a system that avoids this, you are using a server, not all players need to be slowed down to the speed of the currently slowest player's connection.

Instead, it is much better to send requests for commands and moves. For example you have a commando you wish to move from point A to point B. The player who owns the commando unit will click it and then select to move it. The player issued the command with the destination, now the server is checking if the command is feasible. Maybe the player is a hacker or a cheater and does not have a commando, maybe the road is blocked and maybe the unit just died. If the command is accepted by the server after checking, the "Move(Commando,Destination)" packet is sent to all clients including the original player (as a seal of approval) with the time-stap and all needed data. The same thing can be done with "Attack(Commando, Jeep)" commands and Collect(Harvester, resource) commands. You need to present resources as neutral units.

Not all clients will get the reply packet in the same time, remember the time-stamp? To compensate for the delay, a client that gets the order too late, can either animate the unit slightly faster or "teleport" it to it's current correct location. On the player side the movement will start automatically assuming in advance that it is legal to prevent slow response time. If the movement is not accepted, the unit will move backwards which should only happen on very rare occasions.

Sometimes it will not be enough to send only the command such as Move(Commando, (x,y)) and you will need the server to send the resulting orders and way-points to all players. That is because some new building or unit is blocking the shortest path.

I will elaborate if people feel this is valuable.

share|improve this answer
2  
Lots of RTS games use frame locking for online play. –  Jonathan Connell Oct 7 '12 at 10:40
    
@JonathanConnell - I elaborated my answer to address the concerns you raised initially and explain my opinion more precisely. –  Zehelvion Oct 7 '12 at 16:13
2  
"We need a system that avoids this, you are using a server, not all players need to be slowed down to the speed of the currently slowest player's connection." - I wonder if it's fair to let other players kill you when you lagged out. In Starcraft 2, each player has AFAIR 60 seconds of automatic pause, where the game is considered paused after about half or a full second of a major lag. This makes it possible to fix connection issues (turn off Torrent!) and still have same chances as others. That's important, because in RTS good beginning of the game is crucial. –  Markus von Broady Oct 7 '12 at 16:24
    
I don't know if that is fun for the rest of the players. This is definitely an issue that should be adjusted in advance. Perhaps test the connection quality and allow player to play with people with similar latency. I do not know how this would affect the slowest player since his actions will still be reflected due to the time-stap at the time she chose to take them. She will however see the player response later than it actually happened. I think there is room for another question like this. –  Zehelvion Oct 7 '12 at 20:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.