うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】PerlinNoise を利用して Mesh を生成する

PerlinNoise を利用した Mesh を生成するスクリプト以下のようなメッシュを作成できます

using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using Object = UnityEngine.Object;

[RequireComponent(typeof(MeshFilter))]
public class SampleMonoBehaviour : MonoBehaviour
{
    [Range(0.01f, 0.5f)]
    [SerializeField]
    private float _scale = 0.1f;
    [SerializeField]
    private Vector2 _offset = Vector2.zero;
    [SerializeField]
    private MeshFilter _meshFilter;

    [Range(1, 100)]
    [SerializeField]
    private int _sizeX = 30;
    [Range(1, 100)]
    [SerializeField]
    private int _sizeZ = 30;
    
    private Mesh _mesh;
    
#if UNITY_EDITOR
    private void OnValidate()
    {
        UpdateMesh();

    }

    private void Reset()
    {
        _meshFilter = GetComponent<MeshFilter>();
    }
    
#endif

    private void OnDestroy()
    {
        if (_mesh != null)
        {
            Object.Destroy(_mesh);
            _mesh = null;
        }
    }
    
    private void Start()
    {
        UpdateMesh();
    }

    private void UpdateMesh()
    {
        if (_mesh == null)
        {
            _mesh = new Mesh();
            _meshFilter.mesh = _mesh;
        }

        var size = (_sizeX + 1) * (_sizeZ + 1);
        var vertices = new List<Vector3>(size);

        // ノイズから各座標の高さを算出
        for (var x = 0; x <= _sizeX; x++)
        {
            for (var z = 0; z <= _sizeZ; z++)
            {
                var height = Mathf.PerlinNoise(_offset.x + x * _scale, _offset.y + z * _scale) * 10;
                vertices.Add(new Vector3(z, height, x));
            }
        }

        var triangles = new int[_sizeX * _sizeZ * 6];
        var indexes = new int[] {0, _sizeZ + 1, 1, 1, _sizeZ + 1, _sizeZ + 2};

        // トライアングルを設定
        for (var i = 0; i < _sizeX * _sizeZ; i++)
        {
            var triangleIndex = i * 6;
            var vert = i + i / _sizeZ;
            for (var j = 0; j < 6; j++)
            {
                triangles[triangleIndex + j] = vert + indexes[j];
            }
        }
        
        _mesh.Clear();
        _mesh.vertices = vertices.ToArray();
        _mesh.triangles = triangles;

        _mesh.RecalculateNormals();
    }
}