Bending Unity to Carry Spherical Voxel Planets in Planet Nomads
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.
This article covers specific technical aspects of developing a custom C++ voxel terrain engine for Unity that generates procedural, destructible planets of 120 km in diameter. We had to figure out multithreading, effective memory management, lodding, weather effects and advanced physics on a sphere.
While the topic has recently been covered a lot between No Man’s Sky, Elite Dangerous and Star Citizen, none of those games are made with Unity, and since Unity has been dominating the market with millions of developers using it, we figured the technical info from making of Planet Nomads could be useful for others. It also shows how far Unity has gone and can go.
Planet Nomads is a sci-fi sandbox game of survival on alien planets through Minecraft-style building from blocks. Instead of relying on high-power arsenal of guns, the game forces players to rely on their ingenuity while building bases, vehicles and even contraptions and carefuly exploring their surroundings.
One of those amazing contraptions created in the Alpha version of Planet Nomads. By Nomad Dave.
We are coming from a mobile background and Planet Nomads is our first PC game (Win/MAC/Linux). The alpha version was launched on August 25th with some 2500 Alpha Nomads playing and is scheduled for Q1 2017 Early Access/Games in Development launch on Steam and GOG respectively.
Planet Nomads team is currently thirteen people big, but for the purpose of this article it is probably more interesting to know there are six programmers on the team.
SANDY Procedural Terrain Generation Engine as C++ Library
The works on Sandy started in January 2015. When we went to Kickstarter in February 2016 the footage was still shown from an older version of Sandy on a flat plain which we figured we’d round from space-view via shader. But few months before Kickstarter, after taking building, day/night cycle, weather and the future development of Planet Nomads into consideration, we decided it will be worth the additional work and reworked Sandy to generate actual planets for the game.
What Does Sandy Do?
Using a modified Marching Cubes algorithm, Sandy uses noise generators and blends different noises to create a terrain from different materials with varying topography. 3D noise algorithms are interpolated on a sphere. A Google search will reveal a number of articles on procedural generation; this one focuses on individual techniques used in Planet Nomads.
The terrain has different level-of-detail by utilizing a system of chunks saved in an octree structure. Due to the high number of recursions (the root-octree covers the whole planet) it is a non-recursive system. The size of octree chunks can range from 16 m to 128 km. The minimal size of a voxel is one metre and there are 16x16x16 voxels in a single chunk.
C++ Advantages and Problems
The reason for going C++ was faster terrain generation (50% in some cases). Very important, since the visibility in the game is 2 km on the ground and the terrain generation has to keep up with player-built vehicles which can run up to 120 km/h.
Communication between Unity & the C++ Library
Sandy is a C++ plugin imported into Unity, so we had to solve the DLL loading and create an interface for duplex communication - a custom loader. Data between Unity and C++ is copied in blocks using pointers and system functions to copy these blocks (transfer between Unity managed & unmanaged code).
Since Unity API does not support multithreading directly, Planet Nomads uses a plugin to allow threaded calculations in Unity. The terrain generation in the C++ library also runs in threads. On the other hand, game objects with geometry can only be generated in Unity main thread. Therefore Planet Nomads uses a pool of asynchronous actions and sends the resulting calculations into Unity main thread where the required chunk is created. Again greatly speeding the game's performance.
Due to frequent allocations of high amounts of memory in C++ we are using a custom allocation system. Static components of the engine are allocated with Stack Allocator which uses malloc to reserve a memory block which is then assigned to individual modules.
Dynamically created objects are used in a system of pools, memory is allocated in blocks and not individually for each object. This approach greatly increased the generation speed.
Only part of the planet is rendered at a time (either in the player’s vicinity or the planet's visible part when seen from air/space), but players make permanent changes to the whole planet in the course of the game. They can level the terrain, dig tunnels, build bases, outposts and even leave their vehicles parked for later use. These changes need to be saved when the player leaves the respective chunk and loaded when they come back to it.
Planet Nomads uses geographical indexation of this modified data with R*-Tree saved in SQLite database, which enables the engine to quickly load any changes and render them again when needed.
This approach also solved game saving/loading - the whole database is saved into a file and it works on a similar basis as when leaving/entering chunks. The only major letdown was setting up the SQLite library for all platforms to allow multithreaded access and communication between C# and C++.
Different Noises Combined
Graphic artists then take this tech and create the topography of individual biomes by chaining and combining individual noises in a nod-based planet editor.
Early version of nod-based planet editor.
The topography and material create the terrain, which is then populated by trees, bushes, flowers, rocks and other world objects like the ones below.
These world objects are semi-randomly (guided by variables like height, temperature & humidity) placed inside the biomes.
Here's our alpha planet seen "from space". The equator is seemingly placed on the south pole due to perspective.
Below are the examples of how the planet looks on the surface when all the above combine. These screenshots are taken by Nomads from the alpha version of the sandbox game.
There are more interesting technical aspects connected with spherical planets that we had to create custom solution for in Unity (wheel physics, spherical gravity, planet surface rendering with vertex-painted triplanar shader, atmospheric scattering, day/night cycle relative to position on the planet, etc.) We can touch these in future articles. Which aspects sound most interesting to you? Please leave your suggestions in the comments.
For more information on Planet Nomads you can check our developer blog or video journals. If you’d like to see how the tech fares in real life conditions you can preorder Planet Nomads for reduced price now or put it to your Steam wishlist.
Thanks for reading.