2
\$\begingroup\$

Information/context

I'm writing a 2D sandbox game - similar to Terraria. The world is made up of many chunks, in a variable like this:

vector<Chunk> chunks;

There's no need to go too in depth about the Chunk class, but each chunk has these members:

int x, y;
Block blocks[256];

When a chunk is initialized, the blocks are all set (with a Perlin noise based algorithm.) There are 256 blocks per every chunk because a chunk is a 16x16 area filled with blocks. To the loading of the chunks, the members of the Block class are irrelevant.

Question

As the player walks around the world, I obviously need new chunks to load for them to explore. I don't think it needs saying but I shouldn't load every chunk in the world at once because:

  • It would be incredibly inefficient to render (even with my current system of block culling,) and
  • I don't know how many chunks will be in the world - there can be a huge amount, basically as many as the player wants to load.

I've tried a few different (but similar) ways to load and unload the chunks, but none of them worked very well. The main problem with both was that they sometimes gave segmentation faults.

What's the best way to dynamically load and unload chunks in a world?

By "best", I mean the most performance-efficient method.

Keep in mind I can easily load a chunk at any position - this isn't the problem. I just want a way of deciding which chunks to load.

\$\endgroup\$
1
\$\begingroup\$

You are best off loading the chunks around the player. You are already on the right track with your system, and you don't need to make any significant additions.

What you're currently already doing is storing each chunk's world coordinate. All you have to do is to get the player's chunk coordinate and load chunks that are nearby.

There are two ways of doing this, either you need to track chunk coordinates in every object that uses them (that means the player, the objects on the map like monsters and items), or simply extend your position type to include chunk coordinates and just use that for every position in the game (don't forget to override all the operators you use, the bare minimum you'll need is addition/subtraction, scalar multiplication and division, as well as a method to correct any values out of bounds).

After you have that, you simply run a method every now and then that checks what chunks should be visible, loads the missing ones and unloads the invisible ones.

Depending on your game, putting all of that on the same thread that runs your update loop might be not the best idea so you might want to separate some of that into an extra thread.

I have achieved decent results with a n array (vector in C++ parlance I suppose?) that contains currently loaded blocks, which is consulted and the blocks rendered and updated as needed by the game. There's also a method that runs every time the player crosses a chunk border, which checks player's location and fills a queue with the coordinates of chunks that must be loaded, and removes any chunks that aren't used anymore. I also have a separate thread which checks the queue and loads chunks based on those coordinates.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.