Infinite Procedural Terrain with Biomes in Unity (Chunk System)

Biome-Based Procedural Terrain in Unity (Snow, Desert, Forest)
June 29, 2026
Destructible Terrain System in Unity (Complete Guide)
June 29, 2026
Biome-Based Procedural Terrain in Unity (Snow, Desert, Forest)
June 29, 2026
Destructible Terrain System in Unity (Complete Guide)
June 29, 2026

Infinite Procedural Terrain with Biomes in Unity (Chunk System)

Creating massive open worlds is a common goal in modern games. However, generating a huge terrain all at once can quickly destroy performance and memory usage.

The solution used by many games such as Minecraft, Valheim, and No Man’s Sky is a chunk-based infinite terrain system.

Instead of generating the entire world at once, the game dynamically generates terrain chunks around the player as they move.


What Is a Chunk System?

A chunk is a small section of terrain that can be generated, loaded, and unloaded independently.

For example:

  • Each chunk = 50×50 meters
  • The world loads chunks near the player
  • Chunks far away are destroyed or disabled

This makes the world appear infinite while keeping performance under control.


Basic Chunk Architecture

An infinite terrain system usually contains three main components:

  • Chunk Generator – builds mesh data
  • Chunk Manager – loads/unloads chunks
  • Biome System – determines terrain type

Chunk Data Structure

public class TerrainChunk
{
    public Vector2Int coordinate;
    public GameObject chunkObject;
    public MeshRenderer renderer;
    public MeshFilter meshFilter;

    public TerrainChunk(Vector2Int coord, Transform parent)
    {
        coordinate = coord;

        chunkObject = new GameObject("Chunk_" + coord);
        meshFilter = chunkObject.AddComponent<MeshFilter>();
        renderer = chunkObject.AddComponent<MeshRenderer>();

        chunkObject.transform.parent = parent;
    }
}

Tracking Player Position

The chunk manager constantly checks which chunk the player is currently in.

Vector2Int GetPlayerChunk(Vector3 playerPos, int chunkSize)
{
    int x = Mathf.FloorToInt(playerPos.x / chunkSize);
    int z = Mathf.FloorToInt(playerPos.z / chunkSize);

    return new Vector2Int(x, z);
}

When the player moves into a new chunk, the system loads surrounding chunks.


Loading Chunks Around the Player

We generate chunks within a visible radius.

void LoadChunks(Vector2Int playerChunk)
{
    for(int y = -viewDistance; y <= viewDistance; y++)
    {
        for(int x = -viewDistance; x <= viewDistance; x++)
        {
            Vector2Int coord = new Vector2Int(
                playerChunk.x + x,
                playerChunk.y + y
            );

            if(!chunks.ContainsKey(coord))
            {
                CreateChunk(coord);
            }
        }
    }
}

Generating Chunk Terrain

Each chunk generates its terrain mesh using Perlin Noise.

float GetHeight(float worldX, float worldZ)
{
    float noise = Mathf.PerlinNoise(worldX * 0.01f, worldZ * 0.01f);
    return noise * heightMultiplier;
}

Because we use world coordinates instead of local chunk coordinates, terrain transitions remain seamless.


Adding Biomes to Infinite Terrain

Biome selection can be calculated using additional noise maps.

float temperature = Mathf.PerlinNoise(x * 0.003f, z * 0.003f);
float moisture = Mathf.PerlinNoise(x * 0.004f, z * 0.004f);

These values determine which biome appears in that region.

Example biome rules:

  • Low temperature → Snow biome
  • High temperature + low moisture → Desert
  • Medium temperature + high moisture → Forest

Biome Height Differences

float ApplyBiomeHeight(float baseHeight, string biome)
{
    switch(biome)
    {
        case "Snow":
            return baseHeight * 1.8f;

        case "Forest":
            return baseHeight * 1.2f;

        case "Desert":
            return baseHeight * 0.4f;

        default:
            return baseHeight;
    }
}

This creates mountains in snowy areas and flatter terrain in deserts.


Unloading Distant Chunks

To keep memory usage low, chunks far away from the player should be removed.

if(distanceFromPlayer > maxViewDistance)
{
    Destroy(chunk.chunkObject);
}

This keeps only nearby terrain active.


Performance Improvements

  • Use object pooling for chunks
  • Generate terrain asynchronously
  • Use Unity Jobs + Burst for large worlds
  • Use LOD meshes for distant chunks

Real Games Using Chunk Systems

  • Minecraft
  • No Man’s Sky
  • Valheim
  • Astroneer

These games generate huge worlds by loading terrain chunks around the player.


Final Thoughts

Chunk-based procedural terrain is the foundation of infinite worlds in modern games.

By combining chunk generation, noise-based terrain, and biome systems, you can create massive environments that feel natural and endless.

With the right optimization techniques, even extremely large worlds can run smoothly in Unity.

 

Leave a Reply

Your email address will not be published. Required fields are marked *


Skip to toolbar