Server providing real-time game status updates

Currently, my game server is small (one area and ~ 50 AI), and every time it sends state update packets (UDP), it sends the full state to each client. This creates a packet size of ~ 1100 bytes. Almost everything he sends is the following information for all objects:

int uid int avatarImage float xPos float yPos int direction int attackState 24 bytes 

Edit: more efficient structure

 int uid byte avatarImage float xPos float yPos byte direction & attackState 14 bytes 

but I will need to send more information to the entities. For example, I add to this:

 float targetXPos float targetYPos float speed 

Since it is necessary to send more data for each object, I’m moving fast and most likely the maximum packet size has already passed. Therefore, I am trying to come up with several possible ways to fix my problem:

1) Just create a status update package until I leave the room and then leave everything else. Very poor customer view. Not really an option.

2) Just send the data for the N nearest objects to the client. This requires that each state update compute the nearest N for each client. This can take a long time.

3) Some ways to create packages so that I can send several for the same update. Currently, the client assumes that the packages are in the following structure:

 int currentMessageIndex int numberOfPCs N * PC Entity data int numberOfNPCs N * NPS Entity data 

The client then takes this new data and completely overwrites its copy of the state. Since the packages are completely autonomous, even if the client skips the package, this will be normal. I'm not sure how I will implement the idea of ​​several packages for the same update, because if I miss one of them, then what? I cannot overwrite the full, deprecated state with the update, partial state.

4) Just send the actual variables that are changing. For example, for each object, I add one int, which is a bitmask for each field. Things like speed, target, direction and avatar don't need to be sent every update. I will still return to the question of what happens if the client misses a package that really should have updated one of these values. I'm not sure how important that would be. It also requires a bit more client and server side computation to create / read the package, but not too much.

Are there any better ideas?

+4
source share
3 answers

I would go with number 4 and number 2. As you understand, it is usually better to send updates instead of the full state of the game. But make sure you always send absolute values, not deltas, so that no information is lost if the package has been removed. You can use client side dead calculation to make the animation as smooth as possible in the face of tough networking. You must carefully design for this so that it is not important if the packet is lost.

As for number 2, it should not take much time if you think of it. For example, you can divide your playing area into a grid of squares, where each object is always in one particular square and allows the game world to track this. In this case, the calculation of objects in 9 lattice grids is an operation O (1).

+3
source

This type of system is usually solved using Dead Reckoning or a predictive contract algorithm . You cannot depend on whether all customers receive updates simultaneously, so you need to predict positions based on previously known values, and then check these forecasts based on the results generated by the server.

+1
source

One problem that I encountered sending delta updates (basically the 4th option) is that the data may be inoperative or just old, depending on how synchronous your server is, basically the conditions of several races clients updating the server at the same time.

My solution was to send an update notification to all clients with a bitmask setting a bit for each updated item.

The client then requests the current value of the specific data based on the bitmask. It also allows the client to request only the data of interest.

The advantage of this is that he avoids the conditions of the race, and the client always receives the latest value.

The disadvantage is that two-way traffic is required to get the actual value.

UPDATE to demonstrate what I'm trying to do.

Suppose 4 clients A, B, C, D. A and B send simultaneous updates to the mutable state X on server Xa and Xb. As B gets a bit later than A, the final state of X on the server is X = Xb.

The server sends an updated status when it receives it for all clients, so C and D receive an updated status of X, because the delivery order is uncertain. C receives Xa, then Xb and D receives Xb, then Xa, so in this case, clients C and D have different ideas about the state of X, one reflects that the other server does not, it has outdated (or old) data.

On the other hand, if the server just sends a notification that X has changed to all clients, C and D will receive two status notifications for X. They both make requests for the current state of X, and both of them end up with the final state of X on a server that is Xb.

Since the order of the status notification does not matter, since there is no data in it, and the clients issue a request for an updated status for each notification, they both end with consistent data.

Hope it is more clear what I was trying to do.

Yes, this increases the delay, but the developer must decide, more importantly, the delay or the presence of all clients reflecting the same state of the data being changed. It will depend on the data and the game.

0
source

All Articles