Sunday, July 3, 2016

Infinite chunk generation in Unity (4 million blocks - 40 fps)





Voxel-based games become more and more popular these days. It's not surprising, because voxel-based games allow such things as completely dynamic world and procedural world generation. Also, games made of cubes (e.g. Minecraft) look simple yet pretty.
The most important part of a voxel-based game is world. For our project, "The Traveler", terrain generation is critical because the idea of the game is based on travelling and exploration. 
Here are some things we learned from our experience of designing fast, smooth and efficient chunk-based terrain generator.

#1 : Create a mesh for each chunk

Basically, this is the most valuable thing you need to know. Why? At first, our chunk generation used separate colored cubes for the terrain. Results weren’t that good : about 40 fps with only ~5000 blocks(your results may vary). When our team applied a separate mesh generation for each chunk performance skyrocketed to the amount you see in the title.
How is that done? There is a wonderful tutorial on this matter from this guy. To sum up, what you need is:
  1. World controller script, which will control the generation, enabling and disabling the chunks.
  2. Chunk script itself, which will create and hold information about blocks, terrain height(using Perlin noise, supplied with unity or your algorithm of choice), chunks’ mesh and other stuff you will need along the dev process.
  3. Block script, where you will generate vertices(points of mesh), colors, triangles and apply block’s part of the mesh to chunk’s mesh.
A photo of terrain generated using perlin noise in our game called “TheTraveler”(name can change).

#2: Make as many things multithreaded as possible

Yes, you may argue that Unity itself is not entirely multithreaded and its’ API is not thread safe, some of the parts of mesh creation can be made in a seprate thread, provided it does not call any Unity API functions.
Why is it important? As I’ve said, Unity does not fully use all of cores of your CPU, so having CPU working on 50% of its power rather than 20%(depends on the number of cores) will considerably boost your performance. Also, you should bear in mind that thread creation itself has some performance overhead, so the benefits of having multiple threads are more clear when using big chunk sizes.

Partly generated terrain which consists of around 3 million blocks.

#3: Dont use mesh for physics

While I was debugging our game, I found that the application of the same mesh created using mesh generation on mesh collider is using too many CPU cycles. The solution our team found is this - you may use box colliders for physics.
Overview of a chunk. Blue stripes is mesh itself. Green stripes is physics blocks, named "new game object", each with their own collider. Blocks are stretched to reduce performance overhead while creating blocks.

That's all for you folks! If you liked this article and would like to hear more about terraing generation, please subscribe to this blog or our tumblr or twitter accounts. Also, we are planning on writing posts about biome generation, height and color interpolation and much more!
If you have questions regarding chunks, leave a comment. 

No comments:

Post a Comment