I have only vaguely tried to do Multiplayer before (years ago, in QB via serial cable) and I have a question. With an RTS I plan on doing multiplayer, do I have to transfer all the unit data each frame, or what? How did StarCraft handle the load?
How would I sync the units on the computers? would I have to wait for a message to be sent back and forth that the computers are done with each frame before either goes onto the next? That would limit the frame rate to the slowest computer...
~BenDilts( void );
I don''t know how starcraft was done but I believe warcraft II was done being syncing all players to a frame or set of frames (grouping say 1/4 of second worth frames as one). All players waited till there was a ping to go to the next set. Whenever units where ordered to move (or buildings build or etc) the order was first sent to all players, when all players have reponded the order is implemented the beginning of the next frame set. Since all players are running with the units recieiving the same orders at the same time the games (assuming there all the same version) will stay in sync. You could also add a sync check every 5 or 10 seconds that includes a check sum for all the units and values in the game. If any of the check sums don''t match the game is out of sync (due to lost player, packet or bug in the code) and that information must be placed back into sync.
So, like 5 times a second I would pass information around all the players'' computers concerning what units have changed direction, what damage has been dealt, and such like that. But that could really quickly get out of sync, for instance if I passed an integer for which creature did something, and it died halfway through a frame, that would rearrange the #s, messing up all the computers. Hmmmmmmmm.......
I think the most common method is to synchonize user events, such as moving and ordering units to do things. Random variables are synchonized when the game begins so all calls to rand() will result in the same random number. Breaking it down this way you can save on bandwidth as user events are not too large. You''ll need to synchonize or the least verfiy that everyone is alive, every update, though. This will result in the game running at the speed of the slowest computer + worst lag. Lag, latency and drop, will further reduce your update rate, not frame rate as you can use interperlation so everything atleast appears to be smooth.
There is another method you could use, its the server-client model. The above method is a peer to peer method and doesn''t scale well, however is very robust for small set of players. With peer to peer starcraft can synchonize games with over 200 characters moving on each side over a 56k modem in a 4 player game. Unless your planing on supporting over 16 players or your gameplay is very senestive to timming (in the 50ms range or less), you proably want to stick to peer to peer.
Remember, whoever posted that last message, that with client-server if the host of the game got disconnected (as often happens in sc) then that would be the end of the game. I guess there may be a way to make someone else act as the server if this happens... I do think that the client-server model is a very valid architecture for games though. It is a lot easier to stay in sync when everyone is pulling their data off of the same source. Distributed networking is cool too though... I know that starcraft uses UDP. It seems that this would make it more difficult for the games to stay in sync. Things can get lost with udp and no one would ever know.
I think I''ve got the concept down for client-client. Every, say, 1/5 of a second (or whatever) I would have every computer send messages out and then wait until it received enough messages to account for the other computers. The only messages I would really have to send would be small, indexed ones like
You see, I only have to send info for when something is created or a user does something - all movement and collisions would be handled by each computer individually. The above examples would be used with, say, an __int64 flag variable, providing plenty of room. I could even have some MSG_''s overlap if I structured it right...
Also, of course, I would have to check each 1/5 of a second that each computer has the same # of each item - be it units or whatever. So in the end I would end up transferring only at most about 1K per second for a simple-type game, maybe as much as 10-15K per second in an RTS.
Only problem with that would be I would have to remove all queues that are emptied based on computer speed (pathfinding, etc.) to make sure that all the computers'' units are moving exactly the same way.