Efficient way to send player data..

Started by
5 comments, last by oliii 19 years, 6 months ago
Hello. I have been working with diretPlay lately, but this isn't a question directly relating to that. First, I have directPlay connections, server to client, with about 3-4 clients. It is lagging pretty badly. I have very little idea how to send player data efficiently. Currently, I'm sending the player data once every render loop, and if I send much more infrequently, it gets choppy. Is there a more efficient way to send the x,y,z coordinates of a player? (I use float for x, y and z,, so that might be a problem as well.) Thanks, Adam
Advertisement
You send them once every second or less depending on the server connection and use path prediction to fill in the gaps to make it smooth.

Though, if you have the game running at 60 fps, and send 3 32 bit numbers every frame, that's 96bits*60 per second that's 720 bytes per second for each player, that's hardly goind to lag for 3-4 players even if you just have a 56k modem it addds up to about 3K per sec.

You might be sending too much info per frame.
ok, thanks. I'm guessing for path prediction, you would store the players last xyz coordinates, new xyz coordinates, & and figure out the direction the player is going by using those, and then continue moving the player in that direction until you get a new move message?

Tell me if I'm wrong, or if there is a better way.

Thanks.


edit--

Yah, you are right about that math, that seems odd. Perhaps the server is just getting flooded with messages (theres a critical section (only can have 1 thread in it at a time)) so the server is kind of stalling because of that?

.. Off topic - can you use double parenthesis like that lol?

I don't know much about it, but there are levels.
You can just store the direction the player is moving and continue moving the same direction when waiting for the next update.
Or you can record the last x directions the player moved, and while waiting move the player in the average of the last x directions.

x is any number.

That way instead of a straigh line you get a smooth curve that might look more like what the path would be.

eheh @ offtopic

Threaded models for servers are a big performance no-no.
Unless server has multiple cpu's that is.
I'm not sure, but I don't even think it is possible to have single-threaded directPlay =/ Thanks for all of the help so far though. I'm going to have it send once every second without using path prediction first, and see if I get reliable moving.. I'll let you know how it works.
sending data once every frame is _way_ too often. think about it, someone with a higher frame-rate will send more updates more often then someone with a slower computer... you need to send updates at set intervals.

also, you need to give more info. sending at set intervals might not even be appropriate depending on the type of game you're making. what kind of game are you making?

about sending floats, that is probably a bad idea. 4 bytes is a lot for a coordinate when you probably only need 2. you should either roll your own fixed point type, or come up with another solution like using a compressed float. i can't find the link now, but search the forums for "16 bit float". its what im using in my game.

also, keep in mind i just started this whole network programming deal myself, so im not exactly an expert [smile].
FTA, my 2D futuristic action MMORPG
assuming it's a fps, or some fast-paced arcade game.

the update frequency should be relatively low. between 30 fps to 10 fps, depending on the connection of the client (see the CS:S cl_rate variable).

the update from the server to pass entities should be spaced similarly. something between 30 fps to 10 fps.

- When you send the player position from the server back to the clients at low fps, use a prediction/interpolation system on client machines, to calculate the visible position of the player/entity on client machines. that should fix choppiness.

- On the client, the input updates are usually done at relatively high frequency, so there is no lag in the controls. so, on the client, run a physics update on the controled player, using those inputs, like you normally do. that will give the position of the player, as calculated by the client machine. Doing the physics on the client helps removing the lag in the controls, since you do not have to wait for the server to aknowledge the position.

- When it's time to send inputs to the server, batch up the inputs from previous render frames that haven't been sent (say you run inputs at 30 fps, and send at 10 fps, then you'll 3 sets of inputs stored in the message).

The server will process then in order to calculate the position of the player.

With each batch, send the calcualted client position of the player as well. the server, when calculating positions with these inputs, will verify those calculations. if the positions is identical, do nothing. if the position on the server differs from the poisiton calculated by the client, send a correction message back to the client. Positions can diverge when for example, you hit another player, or a mobile object. It's what you see happening when who bump into another player in counterstrike. you get some sort of warping effect. That's also why I believe the physics are so rubbish in CS:S, that is, the barrels and other objects have a force field around them preventing you to get too close to them. Probably to help prediction and avoid extreme warping.

in case of a loss of packets in the input message, also send the packet last sent. so if a message is missed, the server will still receive a constant stream of inputs.

to optimise the data sent both ways, pack data into bitfields, as tight as possible. Compress floats to a minimum size, quaternions, hunt down every single piece of data you send and think if you need to send it, or how many bits you need for it. If an integer is in always in the range [0.1f, 1.4f], maybe it can be packed into a single byte. Also, only send data that has changed since last update. Every now and then, send all the data, just to make sure everything is in sync.

Also, for objects not visible from a player, you can send the update of that object a lot less frequently (say, 30 fps for objects nearby and visible, 20 fps for object visible but quite a long way away, 10 fps for non visible objects, even less for non visible and very far away objects, but you have to have a prediction algo that can run that far in time).

The data rate, upstream and downstream, will be immensly reduced.

for example, when the guys started that stuff, without optimisations of any kind, we would get something like 1-2 megs/second. now, for an identical type of game (fps), we get 6-8 kB/s for a 32 player game. Similar to counterstrike, and I think the method we use is pretty much the same (do physics on client player, send packets of inputs at low fps, server checks, then corrects the client physics, ...). We use a low fps for network updates, so with that kind of rate, we can theoretically go higher, which would improve the prediction (predicting at low fps brings larger errors, obviously).

Everything is better with Metal.

This topic is closed to new replies.

Advertisement