Advertisement

Reducing mobile multiplayer traffic

Started by March 26, 2017 10:11 AM
14 comments, last by hplus0603 7 years, 7 months ago
Let's back up a bit.

Why do you send the ghost players as real-time data?
You should be able to send the course of each ghost player as data ahead of time.
When you do this, you should be able to compress the data really well (gzip or something better) because you can spend whatever resources you want to compress data on the server once, when you store it.

Second, you don't need 64-bit data, at least not for ghost players, because they will just be following the trail of positions, rather than simulate in more detail.
24 bits for x and y and 16 bits for Z should get you all the precision you need, and 32 bits for a full quaternion (with one component dropped) is a common encoding.
That's 8+4 bytes per player state per update.

Also, how are you affecting the local player when they receive their own data back?
The fact that I (as local player) receive data back for the past (half a second or so back) is going to be much more "affecting the simulation" than any rounding/truncation error in the state update.
You can't do full determinism with floating point in Javascript anyway, because you don't know which FPU your client is going to run on.
If you really worry about this, then round/truncate your simulated state each time you take a simulation step, so you know the state is exactly what will be transmitted. (I e, marshal to network, then de-marshal again, as part of simulation loop.)

Anyway. Ghost tracks ahead of time. Highly compressed. Might even pre-install some good ones with the game, so players can practice offline!
enum Bool { True, False, FileNotFound };

Regarding the player id, I simply use the socket id as the player id but it is combined using numbers and letters which has too many bytes. But if I change it to some simpler form the id on the client side will be different from the ones on the server side as I check whether the player is connected using the socket id.


Like I said above, if there are 10 players, each can be identified by 0 to 9. Simply tell each client:

  • "the player with Socket ID 'BlahBlahBlah' is Player 0."
  • "the player with Socket ID 'FooBar' is Player 1."
  • ...
  • "the player with Socket ID 'XYZABC' is Player 9."

You don't need to use one common ID for every system, across every computer. It's very common to have multiple 'IDs' that basically resolve to the same user - e.g. username, user number, email address, local socket port, etc. - and it's common to want to be able to take one ID and look up another, for whatever reason. You can use whichever ID is most convenient, and in this case, a simple index into an array of all your players would be effective.

Besides, I don't know what the Socket ID is in your case, but it doesn't sound like something that is guaranteed to be suitable for sharing.

As with the floating point number, I am using 64 bits floating point which is the standard JavaScript number. It is a double-precision float. When converted to binary data its size is 8 bytes. Hopefully I can find a way to convert it to a single-precision floating point number in JavaScript.

Also JavaScript float number uses IEEE 754 standard, I hope modifying the precision won't affect the real position on browser too much.


The conversion process between 2 types is just about scaling them up or down. It's usually easier to go via a normalised 0 to 1 representation. e.g. If I wanted to represent a number from 0 to 10000 in one byte, I might first divide by 10000 (to give a number from 0.0 to 1.0) and then multiply by 255 (to give a number between 0.0 and 255.0). I can round that to the nearest integer and then it can fit in one byte. The reverse process can expand it back out to the original 0 to 10000 range. This loses some precision, but that may not be a problem. You need to be thoughtful about where you use it, and do the mathematics to see how it would affect you.
Don't do this sort of micro-optimisation until you've tried other approaches, such as simply sending fewer messages.

Now each of my player sends out about 10KB/s which is far from optimized. I hope that I can reduce it to 1-2KB /s so that I can have a few hundreds happy players on the server.


The first thing is that you need to see exactly what this data is and work out why it is this size.
You might want to start a different topic because your needs (top-down MMO-style game with area of interest management, if I remember correctly) are very different to the original poster's needs (fast paced racing game). I suspect that you need to be sending updates less frequently, whereas the original poster may legitimately need to squash their message size down.

Why do you send the ghost players as real-time data?

I'm guessing the original poster is talking about a Trackmania-style game, where you race other players in real-time but can't actually interact with them in any physical sense.

This topic is closed to new replies.

Advertisement