Voxel based world, best practice for sending information

Started by
20 comments, last by hplus0603 11 years, 6 months ago
So, to give you some background.

I have a game that we are making. ( the core elements of the game are already in place and we were working from a Single player perspective only ) Unfortunately, we found that to get the multiplayer to work properly we would need to redesign most or all of the information. We have completed that process of handling how the server sends information to the client the question is now "What data to send the to client? and how often?"

We have a very massive world that is created with a perlin noise algorithm. The map is created in 16x16x255 regions know as "chunks". We want to figure out the best possible method for sending this information from the server to the client application. We would like to avoid the pitfalls that minecraft had with loading chunks outside of the players immediate zone, or having chunks missing all together for an extended period of time. What, if any, methods can we use?

Things of interest:

  • We dont want to spam the client with redundant regions
  • We want to prioritize regions closer to the client so they load first
  • We want to limit how much information is sent and optimize that with the premise that the player cant and doesnt need to see everything.
  • Possible use of super regions ( regions grouped together that have not been modified since last seen )
  • Storing the data, once sent, best possible option for storing it.

We have tried a few methods but wanted to see what people thought was the best route. Also, i am not sure if this post belongs here, it tech falls under game development as well as Networking/Multiplayer. If this needs to be moved please do so as we have no problem with that.
Advertisement
On login information:
If I got it right, the world is randomly generated by the server, the client player will appear at some starting position and you need to send the world information to it?
Is it a 2d game? If it is, I would define a character vision radius and send the information of character vision radius only (probably a little more), then as it moves I would send the information of the region of the direction it is moving.
On update:
In my own hobby project I had a zones approach, the zones were as big as the character vision radius.
In short, I would check the position of the character, then use its vision radius to check what regions it needed information.
At those regions I would check every monster and character in it and see it they were visible and inside the vision radius, then send the information update.
I didn't have any filter on monsters/players that hadn't change, but if I had to implement it, I would use a timestamp (seconds/useconds) of the last change.
My update rate was 20 messages/second, which was pretty smooth for my needs (in my tests, less than 18 started getting bad). But this will depend a lot on how is the player iteraction and how if you use any prediction algorithm in your game.
As of data storing, I used the same objects in the server/client and created/changed then by messages.

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

First: Is the algorithm deterministic? If so, could you generate the chunks on the client as well, without sending data, and only send deltas for things that are changed?

Second, quote:
We would like to avoid the pitfalls that minecraft had with loading chunks outside of the players immediate zone, or having chunks missing all together for an extended period of time.[/quote]

Why do you think that is? And, given what you know about it, what, if anything could be done differently?
enum Bool { True, False, FileNotFound };

On login information:
If I got it right, the world is randomly generated by the server, the client player will appear at some starting position and you need to send the world information to it?
Is it a 2d game? If it is, I would define a character vision radius and send the information of character vision radius only (probably a little more), then as it moves I would send the information of the region of the direction it is moving.
On update:
In my own hobby project I had a zones approach, the zones were as big as the character vision radius.
In short, I would check the position of the character, then use its vision radius to check what regions it needed information.
At those regions I would check every monster and character in it and see it they were visible and inside the vision radius, then send the information update.
I didn't have any filter on monsters/players that hadn't change, but if I had to implement it, I would use a timestamp (seconds/useconds) of the last change.
My update rate was 20 messages/second, which was pretty smooth for my needs (in my tests, less than 18 started getting bad). But this will depend a lot on how is the player iteraction and how if you use any prediction algorithm in your game.
As of data storing, I used the same objects in the server/client and created/changed then by messages.


This is a 3d game,


We have tested out several methods so far, but we need to figure out the best option. None of us are network coders so messing with this and being optimized it our main concern. Should we create everything on the server, or should we have the clients do some of the leg work and only pass updates to the client? security is also an issue as we dont want to make it easy to hack things.

First: Is the algorithm deterministic? If so, could you generate the chunks on the client as well, without sending data, and only send deltas for things that are changed?

Second, quote:
We would like to avoid the pitfalls that minecraft had with loading chunks outside of the players immediate zone, or having chunks missing all together for an extended period of time.


Why do you think that is? And, given what you know about it, what, if anything could be done differently?
[/quote]

Yes it is, and yes we have thought of making seeds on the main server, sending that seed to the client on first initial login, having them generate the world ( or at least a decent size from where their location is ) and then having them update the client as they walk around.

As for the pitfalls of minecraft, they randomly would choose chunks to load, didnt have any priority to them ( they do now ), and the overall chunk loading seemed slow. On our single player version we could update a chunk in less than 5ms so we want to try and keep that as close as possible while going over a network. ( i know that speed of internet has an issue with this ) So the goal is to try to come up with the best possible choice for what the client should handle to what the server should, and how best to pass between the two. Are there any methods to this that are normally used? a library we could look at to understand? That is all we are trying to do is find some form of direction. So many possible avenues and choices! :)
If the world generation is deterministic, the first optimization is to have the server share the generation seed with the client and have client and server generate the base map identically.

From that point, think about how often a "chunk" or "object changes.

If you have a world where objects/chunks rarely change once generated, then you can leverage a hybrid update range system where the player has an update range established in which change objects will be sent and then "remembered" on the server so they don't ever need resent BUT can be updated to the player in the event that object or chunk happens to change (so when the player comes wandering back they see the updated chunk even if they were miles away when the chunk changed.). This means chunks have to know who knows about them in order to update all players accordingly. This optimizes the initial loading of dynamic chunks that changed from the base generation since players are only sent info about chunks as they first come across them. Assuming these chunks don't change often, then, you never have to send the info for that chunk again once it's sent the first time.

If you have objects or chunks that change frequently, then you want to go with a standard update radius approach where dynamic objects are sent to the client when the player comes in range and then "forgotten" about when the player leaves range and resent when they come back in range. This strategy works well for objects that change a lot (like other players running around for instance) on large maps.

Kirk "Runesabre" Black
Enspira Online

Well, some chunks may never change, others will change often. The places that the players live and grow will be the most changed chunks in all of the world. Where chunks that you might mine or travel for quests would be less likely to change.
I generally break my chunks/objects down into 3 basic categories:

1. Chunks that the client and server can generate identically with little to no shared information. (static chunks).
2. Chunks that are dynamic but don't tend to change much or at all once they are created at runtime. For instance, a terrain block that is created and never moves or changes state.
3. Chunks that are dynamic and change a lot (state info updates, position updates, etc). Player objects as an example. They change state a lot and move around a lot.

Then I build a system that can tackle these three major areas.

Kirk "Runesabre" Black
Enspira Online

Problem with shared seed approach is that if you let client be able to generate and cache full terrain data, players will be able to easily check the map for resources (if your game is going to be based on finding them). Usually you generate a lot more than can be seen because without generating its hard to determine which chunks are completly surrounded by others. There is no easy algorithm to categorize chunks as being seen or not seen because it depends on camera, terrain shape etc, so usually you generate full square area around player and only generate smooth mesh / cubes where there is surface border.

Otherwise having seed and sharing only deltas is very tempting. I'm actually interested in any ideas that could prevent players from accessing information about the map easily - think of Minecraft and how players can load map in world viewer and look for resources. If only server knows this information and player receives only visible portion (so the one on the surface) there is no such possibility.

That depends on the game of course, if you don't care about players having advantage because they were able to access world information thats not visible for normal player, then its probably the best route.

Where are we and when are we and who are we?
How many people in how many places at how many times?
You could use a separate seed for placing resources, so you send the normal terrain seed, and then send the visible resources individually (not by sending the seed)

o3o

This topic is closed to new replies.

Advertisement