【Unity】Getting Started with Unity Terrain: Efficiently Building Vast Natural Environments

Created: 2026-02-05

Learn how to create vast natural environments using Unity's Terrain system. Covers terrain sculpting, texture painting, tree and grass placement, and performance optimization.

Overview

"I want to make an open-world game, but how do I create such a huge map?"

Unity Terrain is Unity's built-in landscape creation system that lets you efficiently create vast natural environments. You can sculpt terrain as if painting with a brush, apply textures, and place trees and grass to build realistic worlds.

Creating a Terrain

Simply select GameObject > 3D Object > Terrain from the menu to generate a flat 1000x1000 terrain.

Five Main Tools

ToolDescription
Create Neighbor TerrainsCreates adjacent Terrain tiles
Paint TerrainSculpts terrain and paints textures
Paint TreesPlaces trees
Paint DetailsPlaces grass, flowers, rocks, and other details
Terrain SettingsGeneral settings (size, resolution, performance)

Paint Terrain: Sculpting and Painting

Sculpting Tools

ToolDescription
Raise or Lower TerrainRaises or lowers terrain height (hold Shift to lower)
Set HeightSets a specific height (useful for creating flat plateaus)
Smooth HeightSmooths the terrain
Stamp TerrainStamps the brush shape onto terrain
Paint HolesCreates holes in the terrain (for cave entrances, etc.)

Creating Caves:

  1. Use Paint Holes to create a hole in the terrain
  2. Place a cave 3D mesh at the hole position
  3. Seamlessly connect the mesh edges with the Terrain boundary
  4. Add colliders as needed

Shortcuts

KeyFunction
, .Switch brushes
[ ]Change brush size
- =Change opacity
FFocus camera on cursor position

Terrain Layers: Texture Painting

Creating Terrain Layers

  1. Select the Paint Terrain tool
  2. Select Paint Texture from the dropdown
  3. Click Edit Terrain Layers > Create Layer
  4. Configure textures (Diffuse, Normal Map, Mask Map, etc.)

Painting Textures

  1. Select a Terrain Layer
  2. Set brush size and opacity
  3. Drag across the terrain to paint

Painting at low opacity naturally blends with the layer beneath.

Terrain Layer Limits

Render PipelineMax LayersNotes
URP8 layersPerformance decreases as shader passes increase
Mobile (recommended)4 layersTo maintain performance
Built-inNo limitBut additional draw passes for every 4 layers

Note: As the number of layers increases, draw passes increase and performance degrades significantly. For mobile, keep it within 4 layers.

Trees: Placing Trees

Adding Trees

  1. Select the Paint Trees tool
  2. Click Edit Trees > Add Tree
  3. Select a tree Prefab
  4. Drag across the terrain to place trees (hold Shift to remove)

Mass Place Trees

Use Mass Place Trees to randomly place trees across the entire terrain at once.

Tree Settings

SettingDescription
Bend FactorStrength of wind sway
Billboard StartDistance at which trees switch to billboard rendering

SpeedTree vs Regular Mesh: SpeedTree assets have built-in LOD Groups and automatically transition between LOD levels, while regular meshes only switch to billboards. For high-quality trees, SpeedTree-compatible assets are recommended.

Details: Placing Grass and Details

Detail Types

TypeDescription
GrassRendered as billboards (quads). Lightweight
Detail MeshRendered as 3D meshes. More realistic appearance

Adding Details

  1. Select the Paint Details tool
  2. Click Edit Details > Add Grass Texture or Add Detail Mesh
  3. Drag across the terrain to place

Terrain Settings: Configuration and Performance Optimization

Basic Settings

SettingDescription
Terrain Width/Length/HeightTerrain size
Heightmap ResolutionHeightmap resolution (2^n + 1)
Detail ResolutionDetail resolution

Heightmap Resolution Guidelines

Project ScaleResolutionNotes
Prototype / Small257x257Low memory usage
Typical Game513x513Good balance
Large Open World1025x1025High detail but high memory usage
Very Large2049x2049+Recommended to split into multiple tiles

Detail Resolution Guidelines

ProjectResolutionDetail Resolution Per Patch
Mobile512-10248
PC/Console1024-204816
High Quality2048-409632

Performance Settings

SettingDescription
Pixel ErrorLOD accuracy (5-50 is typical)
Base Map DistanceDistance at which the base map takes over
Detail DistanceDistance at which details are visible
Tree DistanceDistance at which trees are visible
Draw InstancedSpeeds up rendering using GPU Instancing

Draw Instanced: Enabling this option speeds up Terrain rendering using GPU Instancing. This is especially effective when using multiple Terrain tiles.

Wind Settings

Under Terrain Settings > Wind Settings for Grass, you can configure grass sway.

SettingDescription
SpeedWind speed
SizeWind wave size
BendingHow much the grass bends

Grass Tint: The "Grass Tint" setting in the same section adjusts the grass color tone and is separate from wind effects.

Wind Settings Scope:

  • Details (Grass Texture, Detail Mesh) - Affected
  • Trees (placed via Paint Trees) - Not affected (Trees use Bend Factor individually. SpeedTree assets use SpeedTree's own Wind settings)

Multiple Terrain Tiles

For large maps, splitting into multiple Terrain tiles can improve performance.

Creating Tiles

  1. Select a Terrain
  2. Click the Create Neighbor Terrains tool
  3. Choose which direction to create a tile

Tiles are automatically connected seamlessly.

Batch Management with TerrainGroup

For large maps, use Terrain.SetNeighbors() to set up connections between tiles, and the TerrainGroup component to manage multiple Terrains collectively.

Terrain Tools: The Terrain Tools package (pre-installed in some Unity 2022+ versions) makes batch editing of multiple tiles even more convenient.

Heightmap Import/Export

Under Terrain Settings > Import Raw / Export Raw, you can import and export 16-bit RAW format files. Use this for integration with external tools like World Machine or Gaia, or for generating terrain from grayscale images created in Photoshop.

Scripting Terrain Modifications

You can modify terrain from scripts using TerrainData.

using UnityEngine;

public class TerrainModifier : MonoBehaviour
{
    Terrain terrain;
    TerrainData terrainData;

    void Start()
    {
        terrain = GetComponent<Terrain>();
        terrainData = terrain.terrainData;
    }

    // Get/set height (x, y are pixel coordinates)
    // Important: heights array index is [y, x] (row, column) order
    // terrainData.GetHeights(xBase, yBase, width, height) takes (x, y) order,
    // but the returned array is accessed via heights[y, x]
    public void ModifyHeight(int x, int y, float height)
    {
        float[,] heights = terrainData.GetHeights(x, y, 1, 1);
        heights[0, 0] = height;  // Range: 0 to 1
        terrainData.SetHeights(x, y, heights);
    }

    // Convert world coordinates to heightmap pixel coordinates (with bounds checking)
    // For a heightmapResolution of 513, valid pixel coordinates are 0-512
    public Vector2Int WorldToHeightmapCoord(Vector3 worldPos)
    {
        Vector3 terrainPos = worldPos - terrain.transform.position;
        int maxIndex = terrainData.heightmapResolution - 1;
        int x = Mathf.Clamp(
            Mathf.RoundToInt(terrainPos.x / terrainData.size.x * maxIndex),
            0, maxIndex);
        int y = Mathf.Clamp(
            Mathf.RoundToInt(terrainPos.z / terrainData.size.z * maxIndex),
            0, maxIndex);
        return new Vector2Int(x, y);
    }

    // Set texture (Alphamap)
    public void PaintTexture(int x, int y, int layerIndex)
    {
        float[,,] alphas = terrainData.GetAlphamaps(x, y, 1, 1);
        // Reset all layers
        for (int i = 0; i < alphas.GetLength(2); i++)
            alphas[0, 0, i] = 0;
        alphas[0, 0, layerIndex] = 1;
        terrainData.SetAlphamaps(x, y, alphas);
    }
}

Use cases: Procedural terrain generation, runtime terrain modification (digging, leveling, etc.).

Coordinate system note: heightmapResolution and alphamapResolution may return different values. Be careful not to mix up Heightmap and Alphamap coordinates.

Heightmap vs Alphamap Resolution:

PropertyValue PatternExample
heightmapResolution2^n + 1513, 1025
alphamapResolution2^n512, 1024

Procedural Terrain Generation with Perlin Noise

public void GenerateProceduralTerrain(float scale, float heightMultiplier)
{
    int res = terrainData.heightmapResolution;
    float[,] heights = new float[res, res];

    // Add offsets to generate variation,
    // since Mathf.PerlinNoise always returns the same result for the same input
    float offsetX = Random.Range(0f, 10000f);
    float offsetY = Random.Range(0f, 10000f);

    for (int y = 0; y < res; y++)
    {
        for (int x = 0; x < res; x++)
        {
            heights[y, x] = Mathf.PerlinNoise(
                (x + offsetX) / (float)res * scale,
                (y + offsetY) / (float)res * scale
            ) * heightMultiplier;
        }
    }
    terrainData.SetHeights(0, 0, heights);
}

Terrain Tools Package

Installing the Terrain Tools package unlocks additional sculpting tools and advanced features like erosion simulation.

Installation

  1. Select Window > Package Manager
  2. Click the + button and select Add package by name...
  3. Enter com.unity.terrain-tools and install

Additional Tools

ToolDescription
BridgeConnects two points with a bridge
CloneCopies and pastes parts of the terrain
ErosionErosion simulation (weathering, water flow, etc.)
TerraceCreates step-like terraced terrain
NoiseNoise-based terrain generation

Summary

Unity Terrain is a powerful system for efficiently creating large-scale natural environments.

  • Paint Terrain - Sculpt terrain and paint textures with brushes
  • Paint Trees / Paint Details - Quickly place trees and grass
  • LOD and Culling - Robust performance optimization features
  • Multiple Tiles - Scales to massive open worlds

Use Terrain to build your own vast worlds.