3
1

More than 1 year has passed since last update.

Terrainの地形を動的に自動生成する

Posted at

Terrainの地形の保存先

Terrainの地形のデータはTerrainDataの中のheightmapfloatの2次元配列で保存されている。
heightmapは地形の高さを表すテクスチャのようなものであり、要素の中には0.0f~1.0fの値が入っています。
この値はTerrainの高さの割合で、例えばTerrainの高さが5.0fの時、要素の値が0.5fだった場合高さは2.5fとなる。

今回は、このheightmapを変更して地形を作っていきます。

活用する変数とメソッド

TerrainDataを取得する
Terrain terrain = GetComponent<Terrain>();
TerrainData terrainData = terrain.terrainData;
Terrainの大きさを変更する
terrainData.size = new Vector3(x, height, z);
heightmapの解像度を取得する
int heightmapSize = terrainData.heightmapResolution; //地形の大きさ
heightmapを渡す
//地形のデータを渡す
terrainData.SetHeights(0, 0, heightmap);

サンプルプログラム

パーリンノイズを利用した地形を生成するサンプルです。
インスペクターの生成か、Generate()を呼ぶことで生成できます。

TerrainGenerator.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif

[RequireComponent(typeof(Terrain))]
public class TerrainGenerator : MonoBehaviour
{
    [SerializeField] Vector2Int terrainSize; //Terrainのサイズ
    [SerializeField] float height; //Terrainの高さ
    [SerializeField] float relief; //地形の滑らかさ

    float seedX, seedY;

    public void Generate()
    {
        //Terrain関連のコンポーネントを取得する
        Terrain terrain = GetComponent<Terrain>();
        TerrainCollider terrainCollider = GetComponent<TerrainCollider>();
        TerrainData terrainData = terrain.terrainData;

        //シード値を設定する
        seedX = Random.value * 100f;
        seedY = Random.value * 100f;

        //Terrainのサイズを変更する
        terrainData.size = new Vector3(terrainSize.x, height, terrainSize.y);

        //地形に関する変数を用意する
        int heightmapSize = terrainData.heightmapResolution; //地形の大きさ
        float[,] heightmap = new float[heightmapSize, heightmapSize]; //地形のデータ(0 ~ 1)

        //地形を変更する
        for(int y = 0; y < heightmapSize; y++)
        {
            for(int x = 0; x < heightmapSize; x++)
            {
                float sampleX = seedX + x / relief;
                float sampleY = seedY + y / relief;
                float noise = Mathf.PerlinNoise(sampleX, sampleY);

                heightmap[x, y] = noise;
            }
        }

        //地形のデータを渡す
        terrainData.SetHeights(0, 0, heightmap);

        //作ったTerrainDataを渡す
        terrain.terrainData = terrainData;
        terrainCollider.terrainData = terrainData;
    }
}

/// <summary>
/// インスペクターに「生成」のボタンを作る
/// </summary>
#if UNITY_EDITOR
[CanEditMultipleObjects]
[CustomEditor(typeof(TerrainGenerator))]
public class TerrainGeneratorEditor : Editor
{
    public override void OnInspectorGUI()
    {
        TerrainGenerator terrainGenerator = target as TerrainGenerator;

        base.OnInspectorGUI();

        EditorGUILayout.Space();

        if (GUILayout.Button("生成"))
        {
            terrainGenerator.Generate();
        }
    }
}
#endif
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1