Advertisement

How to reduce data sizes?

Started by November 13, 2017 04:40 PM
14 comments, last by Shaarigan 7 years ago

If you want a billion zombies, then synchronising them over a network would be impractical... But you don't have to. You can synchronise their initial conditions and any player interactions, and then run identical updates on each client. 

https://www.gamasutra.com/view/feature/131503/1500_archers_on_a_288_network_.php

1 hour ago, JoeJ said:

Now unpack:

int32 A = compressed & 0xFF; // mask out the other numbers

int32 B = (compressed>>8) & 0xFF; // bit shift and mask 

int32 C = (compressed>>16); // no mask necessary if there is no 4th number

This made things clearer. It turns out I have been using Bit packing for years now, except to me it's always been Texture packing.

So the same principles I would use to store textures can be used here, that makes sense. Considering that textures are made of integers.

 

23 minutes ago, Hodgman said:

But you don't have to. You can synchronise their initial conditions and any player interactions

This is what I am planning now. I can make some kind of walk states, predefined paths and checkpoints. Then just sent a integer with the number related to the path.

This would allow complex movements with a single integer per zombie.

 

 

I don't know why but this whole time I was over complicating things, some kind of mental block.:P Now everything looks so familiar and makes sense. Finally I can start trying this out for real.

Thanks for all of the help.

Advertisement
25 minutes ago, Scouting Ninja said:

This made things clearer. It turns out I have been using Bit packing for years now, except to me it's always been Texture packing.

So the same principles I would use to store textures can be used here, that makes sense. Considering that textures are made of integers.

Ok, but let me make another unrelated example:

vec3 diff = findMe - nodeCenter;

int childIndex = (diff.x>0) | ((diff.y>0)<<1) | ((diff.z>0)<<2);

This way we get 3 bits from 3 comparisons and combine them to a number 0-7. If you order the children of octree in a certain order, this indexes the correct child node in an elegant and effective way. If positions are integers too, this works even without comparisons just by selecting proper bits from position (shift depends on tree level). 

 

Another one is if you have 4 packed values in one, you can add and subtract  to all of them with one op: 0x01020304 + 0x01010101 = 0x02030405. Limited, but there are practical use cases (e.g. to save registers on GPU).

 

What i mean is you should see bit packing more as a subset of bit math, which is a lot more than just compression (but not a total MUST to know).

12 hours ago, Scouting Ninja said:

" 65,542 bytes in a network pack" is what I got from a quick google search. What is the rough amount of 2D zombies I could update with this?

Network packet size differs between networks. Your quoted number looks like the theoretical maximum size, which you only get with very reliable networks, eg loopback over localhost.

LANs are often around 1500. Real Internet, and mobile phone networks are even smaller. Look for the value of "mtu" of a network interface.

If you always want a single network packet for your data, you should look for the minimum guaranteed packet size rather than the largest possible packet size. The former will work on any network.

We have had a huge ammount of AI in one game I worked on this year where we needed to simulate a 40*40km highway updating a huge ammount of vehicles. Updating a million AI agents per frame is not to solve without a huge server farm I think but why do you want to do this?

Lets assume you have a world where each player is able to see all zombies all the time, even then a zombie will typically not do anything every frame rather than stay arround most of the time. Zombies as every other AI needs a reaction time to seem realistic that may be a few hundrets of milliseconds so dosent even need to update every frame too. Lets assume this, then you could separate those million AI agents so that each agent has its reaction latency and update only a few of them every frame. Assuming 60 frames you have a frametime of 16.667 milliseconds per frame assuming a standard zombie reaction time of 200 milliseconds you need to update N / 11 zombies each frame. This are round about 91.000 zombies per frame.

Now I do not know anything about your gameplay but I do not think that you need to update 91.000 zombies each frame. Assuming a standard zombie size of 60*60cm would mean that you have a reagion of 2.730.000^2 cm or 27,3^2 km without any level geometry between them, a pure wall block of zombies. Even when your player has a view distance of 14 km, you wont need to simulate more than 10% of the zombies per frame in this region because any other zombie is too far away to be seen.

If I would make a game with such many AI, I would cheat wherever possible. Separate those zombies into different update loops that run every 10th frame for any AI that is visible (or faster like I did every 3rd frame for the vehicle AI depending on the driving speed), run your update every 20th frame for each AI that is near the player but not visible and also every 100th frame for the rest. I would do this as a sub task so every update has enought time to run and collect updates for your tasks like a packet of 20 or 50 agents data to continiously send over the network.

As I do not think you need to rotate in all three directions, you could pass one rotation value as 3 bit, one ID value as 20 bit and 35 bit for X/Z axis (Y axis is much less, maybe 16 bit) would mean 14 byte (112 bit)  per agent. A 512 byte package can then send updates for 35 agents including some overhead bytes.

Then you should reduce this too by only send updates for agents that have changed there state. I think in a real game this would reduce network traffic to a few kilobytes per second

This topic is closed to new replies.

Advertisement