Jump to content
  • Advertisement
Sign in to follow this  
DracoDraco

Details on sending the game state to clients.

This topic is 2881 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, thanks for any help you can give.
I'm working on a 2D, top-down game. I've read the descriptions of the Source and Unreal network code in the FAQ and they helped alot. I'm trying to go with a pure client-server architecture with client-side prediction and smoothing, but am having troubles planning it out. All the articles I've read focus almost entirely on the synchronization of things like position and orientation, and I've got that working great in my game. But when I try to implement non-continuous events like animations and weapons firing, I get lost.

A specific problem is with animations. If the client presses the attack button, he shouldn't have to wait for a response from the server for his character to play the attack animation. So his character immediately attacks and sends his attack input to the server. The server will then tell all the other clients that this character is attacking. But should the server just not send the message to the original client? And what would this message look like? What if it gets dropped? Is it common for interpolation to be done here as well? This seems like it should be a very common problem but I can't find any discussion or design patterns about it.

A more general description of my problem is that it seems like the game state needs to be completely independent of the previous game state (at least from the client's perspective). So a player can join at any time and read the game state and know everything that is going on. But I can't think of a simple way to represent one-off events in code.

Thanks for reading, sorry if my question is unclear.

Share this post


Link to post
Share on other sites
Advertisement

A specific problem is with animations. If the client presses the attack button, he shouldn't have to wait for a response from the server for his character to play the attack animation. So his character immediately attacks and sends his attack input to the server. The server will then tell all the other clients that this character is attacking. But should the server just not send the message to the original client?

I'd send it. It depends how much you're using unreliable protocols. I tend to just use reliable protocols for everything and send delta state updates that get merged with the full state of entities. Also treating the player no differently than any other entity in the game tends to work well. I wrote this assuming a reliable protocol. I guess if you're using an unreliable protocol then you could try to implement a roll-back mechanism to introduce missed states or have the server queue up and send full-states for entities affected by an unacknowledged state. Honestly I think you could just as easily use a reliable protocol for everything. In my old tests top down shooters worked well with TCP. (Could use multiple reliable UDP channels for position and states separately also).

And what would this message look like? What if it gets dropped?

Assuming an unreliable protocol you normally number packets so the client knows when there's a missing packet. If you assume that all states are important you could have the server send that again.

Looking into the message. I have a link in the previous article to a binary protocol. Often for multiple entities I'll structure the server's per client packet (each packet is constructed just for that individual user based on what they need to know about) like:
[length]
[event id: ServerEvents.EntityEvents]
[int: number of entities]
// Then for each entity:
// Depending on if the entity is known by the client this will be a full state or a delta state
// Basically if it's not in the client's map relating id's to entities then it's a new entity and looks like:
[int: entity id]
[byte: type of entity to create. This is passed to a factory to generate the entity]
// The next data is passed to the entity.DeserializeFull(packet) which will read out the data it requires
[float: position.x][float: position.y][float: velocity.x][velocity.y]
[int: health][int: armor]
// etc.
// If it's in the client's map relating id's to entities then it's a known entity and entity[id].DeserializeDelta(packet) is called
// Delta data looks like:
[bool: position changed]
if true [float: position.x][float: position.y][float: velocity.x][velocity.y]
[bool: health or armor changed]
if true [int: health][int:armor]
[bool: weapon changed]
if true [int: weapon id]
// etc. The same for animation states
// Then the next entities data is here

Hopefully that isn't confusing.


A more general description of my problem is that it seems like the game state needs to be completely independent of the previous game state (at least from the client's perspective). So a player can join at any time and read the game state and know everything that is going on. But I can't think of a simple way to represent one-off events in code.

Read that full and delta state article linked previously. It's essentially a way for tracking the state of objects and who requires the information about changes. A player that joins would be given the full-state of the entities that are of interest to them and then from that point on the changes (delta) to that state.

Have any use cases you're trying to tackle?

Share this post


Link to post
Share on other sites
Very interesting read Sirisi[color="#1C2837"]an, this will prove useful to me (Especially your wiki article) as I'm having the same problems as DracoDraco.
[color="#1C2837"]On a related problem, that maybe DracoDraco has as well, is for example spells in a RPG. When a client decides to cast spell X, he sends the packet to the server. Then what does the server send to the clients ? The server could only send a packet saying "Entity x casted spell y at position z", or it could create an Entity of type spell and the system would synchronize it in the client's world instance. The first method seems to save bandwidth, but it requires the client to handle every spells. The second method seems better as there's no extra system needed on the client side, but it takes more bandwidth. What is your opinion on this ?

Share this post


Link to post
Share on other sites

[color="#1C2837"]synchronize it in the client's world instance. The first method seems to save bandwidth, but it requires the client to handle every spells. The second method seems better as there's no extra system needed on the client side, but it takes more bandwidth. What is your opinion on this ?


There is no right or wrong answer, only engineering trade-offs between things such as bandwidth usage, code complexity, and your ability to ship a fun game.

Pick one, build it, test it. If it works within constraints, ship it!

Note that drawing the effects of the spell (particle systems, playing sounds, etc) can be handled differently than the effects of the spell (losing hit points, adding status effects, etc). I would probably send the "X cast spell S at time T at position P" message to everyone, for display purposes, and then I would simulate the spell on the server, and send actual game state changes separately from the server. Unless I was doing a RTS-like game, where everyone uses a consistent simulation -- in that case, everyone can compute the outcome of the spell deterministically.

Share this post


Link to post
Share on other sites
Note that drawing the effects of the spell (particle systems, playing sounds, etc) can be handled differently than the effects of the spell (losing hit points, adding status effects, etc). I would probably send the "X cast spell S at time T at position P" message to everyone, for display purposes, and then I would simulate the spell on the server, and send actual game state changes separately from the server.

Makes sense. Making extra entities on the server to serve as just graphic dummies seems a bit wasteful. I guess I'll go with the first method, it now seems much more appropriate. Thanks!

Share this post


Link to post
Share on other sites
Hi

I just implemented such a spell system in my game. I do it like this:

When client A casts the spell (in my case shooting an arrow), the client sends the message "cast spell" to the server. The server checks if the player has enough energy to cast the spell. If not, the player sends only to client A "not enough energy". If player A has enough energy and the spell is valid (security check, checksum) the server sends to all players "create animation of spell X". The spell has a velocity V for the arrow. On the server, the time is calculated for the impact with the target: t = (dist to target) / V.

The server knows, how long the arrow will fly until it reaches the taget. On the player clients the animation already started. No information are changed between server and client during the flight of the arrow. Both system (server and client) know the impact time of the arrow. When the spell timer on the server elapses, the server will notify all clients with the message "target X has been hit with Y damage". At the same time the spell animation on the clients should be finished. This works well if you have normal latency. My game servers runs on a V-Server and I use RakNet (UDP) for networking. This system works very well in practice.

Here a screenshot of the player shooting an arrow:
http://www.deltasoft...ages/zdk-03.jpg

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!