Unity程序化生成地形

 制作地形:

  1. 绘制方块
  2. 逐个绘制方块并加噪波高度
  3. 删除Gizmos和逐个绘制

1.draw quad 

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

[RequireComponent(typeof(MeshFilter))]
public class mesh_generator : MonoBehaviour
{
    Mesh mesh;
    Vector3[] vertices;
    int[] triangles;
    // Start is called before the first frame update
    void Start()
    {
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        CreateShape();
        UpdateMesh();
    }

    // Update is called once per frame
    void CreateShape()
    {
        vertices = new Vector3[]
        {
            new Vector3 (0,0,0),
            new Vector3 (0,0,1),
            new Vector3 (1,0,0),
            new Vector3 (1,0,1)

        };

        triangles = new int[]
        {
            0,
            1,
            2,
            1,3,2//1,2,3 will have back face culling problem.
        };
    }

    void UpdateMesh()
    {
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
    }
}

2.逐块生成地形

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

[RequireComponent(typeof(MeshFilter))]
public class mesh_generator : MonoBehaviour
{
    Mesh mesh;
    Vector3[] vertices;
    int[] triangles;

    public int xSize = 20;
    public int zSize = 20;
    //vertex count = (xSize+1)*(zSize+1)

    // Start is called before the first frame update
    void Start()
    {
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        StartCoroutine(CreateShape());
    }
    private void Update()
    {
        UpdateMesh();
    }

    // Update is called once per frame
    //void CreateShape()
    IEnumerator CreateShape()
    {
        vertices = new Vector3[(xSize + 1) * (zSize + 1)];

        for (int i = 0,z =0; z <= zSize; z++)
        {
            
            for(int x = 0; x <= xSize; x++)
            {
                float y = Mathf.PerlinNoise(x*.4f, z * .4f) * 2f;//*.3f  for scale
                vertices[i] = new Vector3(x, y, z);
                i++;
            }

        }
        triangles = new int[xSize*zSize*6];
        int vert = 0;
        int index =0;

        for (int z = 0; z < zSize; z++)
        {
            for (int x = 0; x < xSize; x++)
            {
                triangles[index + 0] = vert + 0;
                triangles[index + 1] = vert + xSize + 1;
                triangles[index + 2] = vert + 1;

                triangles[index + 3] = vert + 1;
                triangles[index + 4] = vert + xSize + 1;
                triangles[index + 5] = vert + xSize + 2;

                vert++;
                index += 6;

                yield return new WaitForSeconds(.01f);
            }
            vert++;//3*3, 行结束后 vert++,vert = 4, index = 18
        }

    }

    void UpdateMesh()
    {
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
    }

    private void OnDrawGizmos()

    {
        if (vertices == null)
            return;

        for (int i = 0; i < vertices.Length; i++)
        {
            Gizmos.DrawSphere(vertices[i], .1f);
        }
    }
}

3.最终效果

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

[RequireComponent(typeof(MeshFilter))]
public class mesh_generator : MonoBehaviour
{
    Mesh mesh;
    Vector3[] vertices;
    int[] triangles;

    public int xSize = 20;
    public int zSize = 20;
    //vertex count = (xSize+1)*(zSize+1)

    // Start is called before the first frame update
    void Start()
    {
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        //StartCoroutine(CreateShape());
        CreateShape();
        UpdateMesh();
    }
    //private void Update()
    //{
    //    UpdateMesh();
    //}

    // Update is called once per frame
    void CreateShape()
    //IEnumerator CreateShape()
    {
        vertices = new Vector3[(xSize + 1) * (zSize + 1)];

        for (int i = 0,z =0; z <= zSize; z++)
        {
            
            for(int x = 0; x <= xSize; x++)
            {
                float y = Mathf.PerlinNoise(x*.4f, z * .4f) * 2f;//*.3f  for scale
                vertices[i] = new Vector3(x, y, z);
                i++;
            }

        }
        triangles = new int[xSize*zSize*6];
        int vert = 0;
        int index =0;

        for (int z = 0; z < zSize; z++)
        {
            for (int x = 0; x < xSize; x++)
            {
                triangles[index + 0] = vert + 0;
                triangles[index + 1] = vert + xSize + 1;
                triangles[index + 2] = vert + 1;

                triangles[index + 3] = vert + 1;
                triangles[index + 4] = vert + xSize + 1;
                triangles[index + 5] = vert + xSize + 2;

                vert++;
                index += 6;

                //yield return new WaitForSeconds(.01f);//yield return 只能在协程(即 IEnumerator 类型的函数)中使用
            }
            vert++;//3*3, 行结束后 vert++,vert = 4, index = 18
        }

    }

    void UpdateMesh()
    {
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
    }

    generate Gizmos
    //private void OnDrawGizmos()

    //{
    //    if (vertices == null)
    //        return;

    //    for (int i = 0; i < vertices.Length; i++)
    //    {
    //        Gizmos.DrawSphere(vertices[i], .1f);
    //    }
    //}
}

附:叠加perlin noise

float y =amplitude1 * Mathf.PerlinNoise(x * frequency1,z * frequency1)
                    + amplitude2 * Mathf.PerlinNoise(x * frequency2, z * frequency2)
                    + amplitude3 * Mathf.PerlinNoise(x * frequency3, z * frequency3)
                        * noiseStrength;

程序化生成颜色

0.用贴图

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

[RequireComponent(typeof(MeshFilter))]
public class mesh_generator : MonoBehaviour
{
    Mesh mesh;
    Vector3[] vertices;
    int[] triangles;
    Vector2[]uvs;

    public int xSize = 20;
    public int zSize = 20;
    //vertex count = (xSize+1)*(zSize+1)

    // Start is called before the first frame update
    void Start()
    {
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        //StartCoroutine(CreateShape());
        CreateShape();
        UpdateMesh();
    }
    //private void Update()
    //{
    //    UpdateMesh();
    //}

    // Update is called once per frame
    void CreateShape()
    //IEnumerator CreateShape()
    {
        vertices = new Vector3[(xSize + 1) * (zSize + 1)];

        for (int i = 0,z =0; z <= zSize; z++)
        {
            
            for(int x = 0; x <= xSize; x++)
            {
                float y = Mathf.PerlinNoise(x*.4f, z * .4f) * 2f;//*.3f  for scale
                vertices[i] = new Vector3(x, y, z);
                i++;
            }
        }

        triangles = new int[xSize*zSize*6];
        int vert = 0;
        int index =0;

        for (int z = 0; z < zSize; z++)
        {
            for (int x = 0; x < xSize; x++)
            {
                triangles[index + 0] = vert + 0;
                triangles[index + 1] = vert + xSize + 1;
                triangles[index + 2] = vert + 1;

                triangles[index + 3] = vert + 1;
                triangles[index + 4] = vert + xSize + 1;
                triangles[index + 5] = vert + xSize + 2;

                vert++;
                index += 6;

                //yield return new WaitForSeconds(.01f);//yield return 只能在协程(即 IEnumerator 类型的函数)中使用
            }
            vert++;//3*3, 行结束后 vert++,vert = 4, index = 18
        }

        uvs = new Vector2[vertices.Length];
        for (int i = 0, z = 0; z <= zSize; z++)
        {

            for (int x = 0; x <= xSize; x++)
            {
                uvs[i]=new Vector2((float)x/xSize,(float)z/zSize);
                i++;
            }
        }

    }

    void UpdateMesh()
    {
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.uv = uvs;

        mesh.RecalculateNormals();
    }

    generate Gizmos
    //private void OnDrawGizmos()

    //{
    //    if (vertices == null)
    //        return;

    //    for (int i = 0; i < vertices.Length; i++)
    //    {
    //        Gizmos.DrawSphere(vertices[i], .1f);
    //    }
    //}
}

1.根据高度给颜色 并用Shader Graph获取vertex color

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

[RequireComponent(typeof(MeshFilter))]
public class mesh_generator : MonoBehaviour
{
    Mesh mesh;
    Vector3[] vertices;
    int[] triangles;
    //Vector2[]uvs;
    Color[] colors;

    public int xSize = 20;
    public int zSize = 20;

    public Gradient gradient;

    float minTerrainHeight;
    float maxTerrainHeight;
    //normalize height




    //vertex count = (xSize+1)*(zSize+1)

    // Start is called before the first frame update
    void Start()
    {
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        //StartCoroutine(CreateShape());
        CreateShape();
        UpdateMesh();
    }
    //private void Update()
    //{
    //    UpdateMesh();
    //}

    // Update is called once per frame
    void CreateShape()
    //IEnumerator CreateShape()
    {
        vertices = new Vector3[(xSize + 1) * (zSize + 1)];

        for (int i = 0,z =0; z <= zSize; z++)
        {
            
            for(int x = 0; x <= xSize; x++)
            {
                float y = Mathf.PerlinNoise(x*.4f, z * .4f) * 2f;//*.3f  for scale
                vertices[i] = new Vector3(x, y, z);

                if(y>maxTerrainHeight)
                    maxTerrainHeight = y;
                if(y<minTerrainHeight)
                    minTerrainHeight = y;

                i++;
            }
        }

        triangles = new int[xSize*zSize*6];
        int vert = 0;
        int index =0;

        for (int z = 0; z < zSize; z++)
        {
            for (int x = 0; x < xSize; x++)
            {
                triangles[index + 0] = vert + 0;
                triangles[index + 1] = vert + xSize + 1;
                triangles[index + 2] = vert + 1;

                triangles[index + 3] = vert + 1;
                triangles[index + 4] = vert + xSize + 1;
                triangles[index + 5] = vert + xSize + 2;

                vert++;
                index += 6;

                //yield return new WaitForSeconds(.01f);//yield return 只能在协程(即 IEnumerator 类型的函数)中使用
            }
            vert++;//3*3, 行结束后 vert++,vert = 4, index = 18
        }

        //uvs = new Vector2[vertices.Length];
        colors = new Color[vertices.Length];
        for (int i = 0, z = 0; z <= zSize; z++)
        {

            for (int x = 0; x <= xSize; x++)
            {
                //uvs[i]=new Vector2((float)x/xSize,(float)z/zSize);
                float height = Mathf.InverseLerp(minTerrainHeight, maxTerrainHeight, vertices[i].y);
                colors[i] = gradient.Evaluate(height);
                i++;
            }
        }

    }

    void UpdateMesh()
    {
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.colors = colors;

        mesh.RecalculateNormals();
    }

    generate Gizmos
    //private void OnDrawGizmos()

    //{
    //    if (vertices == null)
    //        return;

    //    for (int i = 0; i < vertices.Length; i++)
    //    {
    //        Gizmos.DrawSphere(vertices[i], .1f);
    //    }
    //}
}