🔒 Locked
RTS netcode
Advertisement
Original Post
Okay here is the situation: Im developing a small rts. I just started coding the unit code, and I want to make sure it suports multiplayer from the start. I have read the "Manage your Units" tutorial on flipcode and the "Age Of Empire 2" netcode article on gamasutera. Now I was wondering if anybody got some hints on how to implent this corretly. (stuff that dont work and stuff that does work ) Also if anyone know a tutorial/article/source on this subject I would be glad to know, so that I can do as much reseach before getting my feats too wet. (I have already written a udp library that I want to use. ) - CoMaNdore
Sorry Tazzel3D for being unclear, this question was mostly for those who
had already implented a RTS with networking, and had some tips to offer.
Like: Dont send X packet, send instead Y twise and interpolate..
Okay, what I am wondering about is what kind of packet/data to send between the players. And how often I need to send it.
Any ideas ?
had already implented a RTS with networking, and had some tips to offer.
Like: Dont send X packet, send instead Y twise and interpolate..
Okay, what I am wondering about is what kind of packet/data to send between the players. And how often I need to send it.
Any ideas ?
Well, imho, the simplest way to do this would be to make the RTS 100% deterministic and only send orders to and fro. So what the player sends to the server is "I told unit Y to do X" and the server says "on tick Z, unit Y was told to do X". The server simply tells the user what tick the game is on, and the user can never advanced past the server's current time. You'd have to make the game discrete-time and calculate _every_ frame (no skipping any) and not use any random features (unless all machines share a rand function and use a common seed). No threading allowed within game logic.
Essential the game would be mathematically turn-based, but run as an RTS.
This system has tons of faults, of course (if you lose sync the game is toast) but would be the tightest, tinyest possible netcode, and probably the easiest to implement netcode.
Essential the game would be mathematically turn-based, but run as an RTS.
This system has tons of faults, of course (if you lose sync the game is toast) but would be the tightest, tinyest possible netcode, and probably the easiest to implement netcode.
Quote:
Original post by Gizz Quote:
Original post by Pxtl
This system has tons of faults, of course (if you lose sync the game is toast) but would be the tightest, tinyest possible netcode, and probably the easiest to implement netcode.
And you could request a full resync if you detect that you lost sync.
How would the re-sync work? I can think of two ways..
1) Requesting all the game data as is stored in memory on the server. Maybe some check-summing of sections of stored data should be performed to locate the erroneous data?
2) Requesting a list of all the actions performed by all players.
Are either of them options even viable?
ps. Sorry if this is straying from the topic too much :)
no this is eactly the kind of things that I was looking for.
About re-sync:
I think that since in my game I probly wont have deforable
terrain. I will just first recv a list of all entitys checksum.
*one per entity*
What checksum algo should I use to avoid overkill, and still compenstate for floating point in-precision?
And then the client iterate over the checksums and compare them to its own unit checksums. If the checksum dont match then the client request the unit data. The game must be paused while the re-sync occurs. After the unit sync step I would send the rand
data. ( Im tinking that the server and the client have a function
like:
I probly also have a block with the player managment stats. Like
resources unit techs and so on.
Does this sound viable ?
About re-sync:
I think that since in my game I probly wont have deforable
terrain. I will just first recv a list of all entitys checksum.
*one per entity*
What checksum algo should I use to avoid overkill, and still compenstate for floating point in-precision?
And then the client iterate over the checksums and compare them to its own unit checksums. If the checksum dont match then the client request the unit data. The game must be paused while the re-sync occurs. After the unit sync step I would send the rand
data. ( Im tinking that the server and the client have a function
like:
// pesudo c++ without error checkingvoid SetRandIndex( .. );int GetRandIndex( );unsigned int GetRandValue(){ // RandArray[] is pre defined alike on the server and the client // and will be controled by the [Set|Get]RandIndex functions return( RandArray[GetRandIndex()] );}I probly also have a block with the player managment stats. Like
resources unit techs and so on.
Does this sound viable ?
Making everything lock-step, with pipelined commands (i e, a command issued at frame 12 starts executing on frame 15 or so), is a low-bandwidth way of making sure everything works right. I believe Warcraft III does this, for example. The major vulnerability of this approach is that the client machines need to have all the state of all the enemy units, so a cheat could be written to read that information out of the running process and display a super-map to the player. You might be able to work around that cheat through clever game design.
Btw: a simple way to compensate for floating-point problems is to round to a specific precision each frame. Thus, you might round position to nearest millimeter each frame. If you're off by less than half a millimeter compared to the others, you'll still round to the same value.
Btw: a simple way to compensate for floating-point problems is to round to a specific precision each frame. Thus, you might round position to nearest millimeter each frame. If you're off by less than half a millimeter compared to the others, you'll still round to the same value.
Quote:
Original post by Zanthos
How would the re-sync work? I can think of two ways..
1) Requesting all the game data as is stored in memory on the server. Maybe some check-summing of sections of stored data should be performed to locate the erroneous data?
2) Requesting a list of all the actions performed by all players.
Are either of them options even viable?
ps. Sorry if this is straying from the topic too much :)
Actually, I was thinking something along the line of #1. By making small subset of things that are in sync, you can narrowdown your diverging entity quickly (instead of having only 1 checksum englobing everything). This way, once you detect that something is out of sync, you only request a re-sync for a small pack of entities. Of course, the granularity will need to be adjusted depending on the number of entities.
Gizz
hplus0603: I was planning to use a lockstep aproach.
I have some issues with this tho that some of you might be able to help me with:
The point of lockstep is to make sure that we have kN number of
logical updates each second. And still allow the render to render at full speed (and interpolate between the frames).
How can you sync the client and the server right?
Should the clients just keep rendering and the server tell each
client to start "step X" (The server runs a lockstep)
I would ofc need to compensate for latency between between client and the server.
Or should each client and server run a lockstep.
One issue that I can think of then is how can a client that LAGS
behind and cant keep up with all the other players notify the server that it cant keep up. And again how can the server notify the other clients that they need to wait?
Also how many logic frames per second should I have ?
I have some issues with this tho that some of you might be able to help me with:
The point of lockstep is to make sure that we have kN number of
logical updates each second. And still allow the render to render at full speed (and interpolate between the frames).
How can you sync the client and the server right?
Should the clients just keep rendering and the server tell each
client to start "step X" (The server runs a lockstep)
I would ofc need to compensate for latency between between client and the server.
Or should each client and server run a lockstep.
One issue that I can think of then is how can a client that LAGS
behind and cant keep up with all the other players notify the server that it cant keep up. And again how can the server notify the other clients that they need to wait?
Also how many logic frames per second should I have ?
Quote:
Original post by CoMaNdore
One issue that I can think of then is how can a client that LAGS
behind and cant keep up with all the other players notify the server that it cant keep up. And again how can the server notify the other clients that they need to wait?
The clients are expected to send out exactly one input packet per frame. So the client waits for a full set of input packets to be received each frame from every player, otherwise you'll have to wait.
CoMaNdore-
I've implemented netcode in my RTS and took quite a naive approach, which worked fine.
The server made all of the decisions and clients simply requested actions, which the server would then validate and apply to the game world. It then propogated these changes back to all the clients.
For certain units, such as aeroplanes, I sent out their position information every few frames. For most of my units I simply sent out position information when they arrived at a new 'square' on my terrain. This kept all the units synced quite well.
For advice....I think the best thing you can do is plan as much of the netcode before you begin as possible. If you can have a concrete plan for the netcode before you even begin the game engine then you can make informed decisions when designing the rest of the system, to make sure it fits in with your netcode.
Doolwind
I've implemented netcode in my RTS and took quite a naive approach, which worked fine.
The server made all of the decisions and clients simply requested actions, which the server would then validate and apply to the game world. It then propogated these changes back to all the clients.
For certain units, such as aeroplanes, I sent out their position information every few frames. For most of my units I simply sent out position information when they arrived at a new 'square' on my terrain. This kept all the units synced quite well.
For advice....I think the best thing you can do is plan as much of the netcode before you begin as possible. If you can have a concrete plan for the netcode before you even begin the game engine then you can make informed decisions when designing the rest of the system, to make sure it fits in with your netcode.
Doolwind
Doolwind, some questions:
You made the netcode quite a like a FPS?
Pluss some optimations to be able to handle the larger number
of units.
Say you click on Unit4 and order it to move to a place on the
entire other side of the map. Now the client would first "parse"
this command into a lot of smaller onces>
move to x1,y1
move to x2,y2
move to x3,x3
...
Until you have genrated a path to reach the goal.
Then you would send the first command (move Unit4 to x1,y1)
to the server witch would check it for terrain collition, and add
it to the list of moving units.
Now each "logic frame" the server would send out to all clients the vel, pos, and dir of Unit4? And ofc test it for collition and such as well. And when it reached its goal, the client would
send its next command( move Unit4 to x2, y2)
Is it somthing like this you have implented ?
Also any chance that I might be able to take a look at the source
for your rts game?
edit: Does the server perform some sort of culling to make sure
it only send data for units that the client can "see" ?
Thanks for the help, CoMaNdore
You made the netcode quite a like a FPS?
Pluss some optimations to be able to handle the larger number
of units.
Say you click on Unit4 and order it to move to a place on the
entire other side of the map. Now the client would first "parse"
this command into a lot of smaller onces>
move to x1,y1
move to x2,y2
move to x3,x3
...
Until you have genrated a path to reach the goal.
Then you would send the first command (move Unit4 to x1,y1)
to the server witch would check it for terrain collition, and add
it to the list of moving units.
Now each "logic frame" the server would send out to all clients the vel, pos, and dir of Unit4? And ofc test it for collition and such as well. And when it reached its goal, the client would
send its next command( move Unit4 to x2, y2)
Is it somthing like this you have implented ?
Also any chance that I might be able to take a look at the source
for your rts game?
edit: Does the server perform some sort of culling to make sure
it only send data for units that the client can "see" ?
Thanks for the help, CoMaNdore
CoMaNdore-
When the user on the client clicks a unit4 to move to (x,y), the client simply sends that message to the server (move unit4 to x,y). The server then does a quick path finding operation and sets the state of it's local copy of unit4 to start moving towards that location.
Within that calculation the server now has a list of squares the unit needs to travel along to get to the destination. It sends to all the clients the first few squares the unit needs to go to. The clients then move their unit4 to those first few squares. Before the server's unit4 reaches the end of those squares it sent, it sends the next few squares the unit needs to move and so on until it reaches it's goal.
So the server might send 5 squares worth of movement, then after it reaches the 3rd it sends the next 5. This way if there is any lag issues the clients can continue moving.
PM me and we can talk about you having a look at some of the source code.
As I said It's just a naive system, in the future I was thinking of adding some culling in, but it worked fine for a first version so I was happy with it.
To let you know...I was making this RTS during my spare time as a demo to get a job in the games industry. I was only about 8 months into development when I was offered a job so it is not yet a complete game, however the core engine is fairly complete.
Doolwind
Quote:
Say you click on Unit4 and order it to move to a place on the
entire other side of the map.
When the user on the client clicks a unit4 to move to (x,y), the client simply sends that message to the server (move unit4 to x,y). The server then does a quick path finding operation and sets the state of it's local copy of unit4 to start moving towards that location.
Within that calculation the server now has a list of squares the unit needs to travel along to get to the destination. It sends to all the clients the first few squares the unit needs to go to. The clients then move their unit4 to those first few squares. Before the server's unit4 reaches the end of those squares it sent, it sends the next few squares the unit needs to move and so on until it reaches it's goal.
So the server might send 5 squares worth of movement, then after it reaches the 3rd it sends the next 5. This way if there is any lag issues the clients can continue moving.
Quote:
Also any chance that I might be able to take a look at the source
for your rts game?
PM me and we can talk about you having a look at some of the source code.
Quote:
Does the server perform some sort of culling
As I said It's just a naive system, in the future I was thinking of adding some culling in, but it worked fine for a first version so I was happy with it.
To let you know...I was making this RTS during my spare time as a demo to get a job in the games industry. I was only about 8 months into development when I was offered a job so it is not yet a complete game, however the core engine is fairly complete.
Doolwind
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement