Unity 地形设计之多个Perlin地形以及插件Editor GUI table的使用(六)

这篇我们设置多个Perlin地形,首先把需要用到的插件Editor GUI table导到项目中。

编辑CustomTerrain脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
using UnityEditor;

public class CustomTerrain : MonoBehaviour {

    public bool resetTerrain = true;
    
    //MULTIPLE PERLIN --------------------
    //这个类提供Perlin参数,由它我们可以创建perlin参数列表
    [System.Serializable]
    public class PerlinParameters
    {
        //存储缩放值
        public float mPerlinXScale = 0.01f;
        public float mPerlinYScale = 0.01f;
        //分型布朗运动新增属性
        public int mPerlinOctaves = 3;
        public float mPerlinPersistance = 8;
        public float mPerlinHeightScale = 0.09f;

        public int mPerlinOffsetX = 0;
        public int mPerlinOffsetY = 0;
        public bool remove = false;
    }
    //创建我们的第一个列表
    public List<PerlinParameters> perlinParameters = new List<PerlinParameters>()
    {
        new PerlinParameters()//列表有一个参数
    };
    //这个函数每次创建新的高度图时使用
    float[,] GetHeightMap()
    {
        if (!resetTerrain)
        {
            return terrainData.GetHeights(0, 0, terrainData.heightmapWidth,
                                                terrainData.heightmapHeight);
        }
        else
            return new float[terrainData.heightmapWidth,
                             terrainData.heightmapHeight];

    }

    //获取地形(物体)对象
    public Terrain terrain;
    //TerrainData里有地形所有的数据
    public TerrainData terrainData;
    //每次编辑完脚本内容返回编辑器时运行后会执行此方法
    private void OnEnable()
    {
        //初始化地形数据 先获取地形再获取本身的地形数据
        terrain = gameObject.GetComponent<Terrain>();
        terrainData = Terrain.activeTerrain.terrainData;
    }
    //这是多个Perlin地形
    public void MultiplePerlinTerrain()
    {
        float[,] heightMap = GetHeightMap();
        for (int y = 0; y < terrainData.heightmapHeight; y++)
        {
            for (int x = 0; x < terrainData.heightmapWidth; x++)
            {
                //遍历表中的每组参数通过分形布朗运动,叠加将其应用于地形新高度
                foreach (PerlinParameters p in perlinParameters)
                {
                    heightMap[x, y] += Utils.fBM((x + p.mPerlinOffsetX) * p.mPerlinXScale,
                                                 (y + p.mPerlinOffsetY) * p.mPerlinYScale,
                                                    p.mPerlinOctaves,
                                                    p.mPerlinPersistance) * p.mPerlinHeightScale;
                }
            }
        }
        terrainData.SetHeights(0, 0, heightMap);
    }

    public void AddNewPerlin()//添加一个数据
    {
        perlinParameters.Add(new PerlinParameters());
    }

    public void RemovePerlin()//删除一个数据
    {
        List<PerlinParameters> keptPerlinParameters = new List<PerlinParameters>();
        for (int i = 0; i < perlinParameters.Count; i++)
        {
            if (!perlinParameters[i].remove)
            {
                keptPerlinParameters.Add(perlinParameters[i]);
            }
        }
        if (keptPerlinParameters.Count == 0) //don't want to keep any
        {
            keptPerlinParameters.Add(perlinParameters[0]); //add at least 1
        }
        perlinParameters = keptPerlinParameters;
    }

}

编辑CustomTerrainEditor脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using EditorGUITable;
[CustomEditor(typeof(CustomTerrain))]
public class CustomTerrainEditor : Editor {
    SerializedProperty resetTerrain;
    GUITableState perlinParameterTable;//表内容和关联的序列化属性放在一起
    SerializedProperty perlinParameters;//具有Perlin参数的序列化属性
    bool showMultiplePerlin = false;//可折叠属性面板
    private void OnEnable()
    {
      
        resetTerrain = serializedObject.FindProperty("resetTerrain");
        perlinParameterTable = new GUITableState("perlinParameterTable");
        perlinParameters = serializedObject.FindProperty("perlinParameters");

    }
    //绘制编辑面板
    public override void OnInspectorGUI()
    {
        //更新所有序列化的值
        serializedObject.Update();
        //获取自定义的地形属性脚本组件
        CustomTerrain terrain = (CustomTerrain)target;
        EditorGUILayout.PropertyField(resetTerrain);
        #region     
        showMultiplePerlin = EditorGUILayout.Foldout(showMultiplePerlin, "Multiple Perlin Noise");
        if (showMultiplePerlin)
        {
            EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
            GUILayout.Label("Mulitple Perlin Noise", EditorStyles.boldLabel);
            //相当于把所有的序列化属性放在表格里
            perlinParameterTable = GUITableLayout.DrawTable(perlinParameterTable,
                                   serializedObject.FindProperty("perlinParameters"));

            GUILayout.Space(20);
            EditorGUILayout.BeginHorizontal();//加减号按钮水平相邻,放在一个水平块儿中实现
            if (GUILayout.Button("+"))
            {
                terrain.AddNewPerlin();
            }
            if (GUILayout.Button("-"))
            {
                terrain.RemovePerlin();
            }
            EditorGUILayout.EndHorizontal();//加减号按钮水平相邻
            if (GUILayout.Button("Apply Multiple Perlin"))
            {
                terrain.MultiplePerlinTerrain();
            }
        }
    #endregion
    //应用发生的所有更改
    serializedObject.ApplyModifiedProperties();

    }
   
}

分形布朗运动工具类Utils:

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

public static class Utils {
    // 分形布朗运动函数,静态方法方便从外部调用
    //要在热点地图中传递一个位置x,y,
   
    public static float fBM(float x, float y, int oct, float persistance)
    {
        float total = 0;
        float frequency = 1;//频率是波的紧密程度,一个八度(octave)对应着频率上的加倍或减半
        float amplitude = 1;//振幅
        float maxValue = 0;
        for (int i = 0; i < oct; i++)//遍历每个八度
        {
          
            total += Mathf.PerlinNoise(x * frequency, y * frequency) * amplitude;//通过循环叠加噪声
            maxValue += amplitude;//最大值是每个oct使用的振幅相加
            amplitude *= persistance;//以一定的比例降低噪声的振幅
            frequency *= 2;//以一定的倍数连续升高频率
        }

        return total / maxValue;//注意返回值降到0到1之间的范围内
    }

}

发布了122 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40229737/article/details/103491156