Terrain Leveling

So finally here’s my example code.:wink: Simply drag this script on the terrain and assign a primitive cube to the script that sits ontop of the terrain. The code will raise the terrain up to the height of the cube. You can even scale the cube as you like to get rectangular areas.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// Terrain example for forum.unity.com by Zer0Cool
/// </summary>
public class ModifyTerrain : MonoBehaviour
{

    [Tooltip("Assign a cube primitive here placed on the Unity terrain. You can even scale the cube if you like.")]
    public Transform cube;

    [Tooltip("Resets the terrain under the cube to zero high.")]
    public bool resetTerrainToZero;

    private Vector3 rectCenter;
    private float rectSizeX;
    private float rectSizeY;

    private Vector2 rectCenterMap = Vector2.zero;
    private int rectSizeXMap;
    private int rectSizeYMap;
    private float rectSizeHMap;

    private float[,] heightMap;

    void Start()
    {
        FlattenTerrain();
    }

    void FlattenTerrain()
    {
        rectCenter = cube.transform.position;
        rectSizeX = cube.transform.localScale.x;
        rectSizeY = cube.transform.localScale.z;

        Terrain ter = GetComponent<Terrain>();
        TerrainData terData = ter.terrainData;
        int Tw = terData.heightmapResolution;
        int Th = terData.heightmapResolution;
        heightMap = terData.GetHeights(0, 0, Tw, Th);

        // Determine the world coordinates
        float scalex = terData.heightmapResolution / terData.size.x;
        float scaley = terData.heightmapResolution / terData.size.z;
        rectCenterMap = new Vector2((int)(rectCenter.x * scalex), (int)(rectCenter.z * scaley));

        rectSizeXMap = (int)((rectSizeX * scalex) / 2f);
        rectSizeYMap = (int)((rectSizeY * scaley) / 2f);
        rectSizeHMap = rectCenter.y / terData.size.y;

        for (int Ty = 0; Ty < Th; Ty++)
        {
            for (int Tx = 0; Tx < Tw; Tx++)
            {
                PunchOutRectangle(Ty, Tx);
            }
        }

        terData.SetHeights(0, 0, heightMap);
    }

    public void PunchOutRectangle(int xrow, int yrow)
    {
        if ((xrow <= (rectCenterMap.x + rectSizeXMap)) && (xrow >= (rectCenterMap.x - rectSizeXMap)) &&
           (yrow <= (rectCenterMap.y + rectSizeYMap)) && (yrow >= (rectCenterMap.y - rectSizeYMap)))
        {
            // Raise the terrain to center of the cube
            heightMap[yrow, xrow] = rectSizeHMap;
            if (resetTerrainToZero) heightMap[yrow, xrow] = 0f;
        }
    }
}

2 Likes