Unity Procedural Generation Tutorial
Procedural generation is a way to create data in a game via an algorithm. This is useful for generating levels or even entire games!
In this project we will be creating a procedurally generated map. To start, we will need some terrain. We will create a new empty game object in the Hierarchy window called Terrain.
The Level Tiles are the lowest level of detail meshes that will be loaded into the world during runtime. The tiles each parse their height data in worker threads which are then composed into new vertex data and normal vectors for the actual Mesh class instances that render them. This process is handled in a coroutine so only a couple of mesh tiles are composed (and rendered) per frame.
When a Level Tile is created it also has a Sprite Editor Outline that will be used to edit its outlines in the game. The outlines help to avoid stitching issues at runtime. The tiles will be sized to fit into a cell of the Unity Tilemap but they could have different widths depending on their PPU value.
When the Generator assembles the levels it will copy each Level Tile into shared tilemaps, it will also recompute collider shapes which can impact performance. This is why it’s important to limit the number of layers that have colliders.
Creating a game level by hand is one way to go, but procedural generation is another way. This is where you create a machine or set of rules that can be fed some initial start values and then automatically generate a level for you.
This can be used for 2D terrains like tile maps or 3D terrains such as in the case of this tutorial. Basically you want to take some sort of noise and map it to the surface of your terrain.
This is done with the MapGenerator component in our example code. Within the inspector window you will notice some new fields. The first is the tiles array which will store all the different types of tiles we are generating. The next is a set of private integers starting with the tileCount integer which will control how many tiles Unity can create. This will be a value that can be adjusted from within the editor as well.
The biome map is a series of fairly simple operations stacked on top of each other. This layer uses a nearest-neighbor upscaling of the terrain map and then adds some extra details, like a biome texture based on the color of the biome.
This is done using a mix of noise functions (Simplex, OpenSimplex, Perlin, value, diamond square displacement and inverse Fourier transform). The biome map also links the biome to the terrain height, which is important because it prevents bizarre things like a mountain beach.
It is also responsible for determining which temperatures the region will be in (Warm, Temperate, Cold or Freezing) which will eventually determine which biomes it can turn into. The next layers are responsible for adding more nuances like cliffs and rivers. This will all work to give a more natural feeling to the world and hopefully make it feel more realistic. Other generation stages are planned to be added before and after this biome mapping.
A lot of games use procedural generation to package a huge amount of content in relatively small programs. This could be a 3D model, a sprite or UI element, or even screen effects like a particle system. The basic construct that represents these things in Unity is a mesh.
A mesh contains a set of points, or vertices, in a 3D space and a set of triangles that connect those points. There are many different algorithms for generating various kinds of meshes, and they all have advantages and disadvantages.
Procedural generation offers nearly infinite ways to play a game or decorate a scene without having to painstakingly craft every detail by hand. However, it also opens the door to potentially disastrous bugs and imbalances, such as a level with no way out or too many enemies in a given area. To avoid these issues, a number of rules must be implemented to guide the computer as it generates these levels.