Bootstrap

Unity程序化地形教程 第二期 噪声图的完善和更多细节添加

Unity程序化地形教程 第二期 噪声图的完善和更多细节添加

前言:完整的程序化地形教程在我的主页相关专栏中,目前正在持续更新,可以添加收藏,方便日后查找

零、学完本期能够实现的效果

书接上期,学完之后相比上期能够有更多的细节和优化,话不多说,赶快开始吧!
在这里插入图片描述

一、noise脚本的属性值添加

相比上一期noise的属性值,这一期里面新添加了五个属性值,我们在上图中也能看到相关的效果,这五个值分别是

 public int octaves; //八度数量 高峰的数量
 public float persistance; //持久值 可以理解为平滑还是不平滑
 public float lacunarity; //缺陷 可以理解为粗糙度
 public int seed;  //地图种子 相对于偏移量来说能够更大程度上去改变地图的整体面貌
 public Vector2 offset; //偏移量 

在这里我们添加上相关属性后的代码,各个函数都有相关的注释

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

public static class Noise
{
    public static  float[,] GenerateNoiseMap(int mapWidth,int mapHeight,int seed, float scale,int octaves,float persistance,float lacunarity,Vector2 offset)  //利用噪声来设置地形的高低
    {                                                                     //回到相同地图的种子       新增八度音阶数量    持久值      缺陷    
        float[,] noiseMap = new float[mapWidth, mapHeight]; //两个维度的浮点数类型的数组

        //创建一个系统点随机对象  伪随机数生成器
        System.Random prng = new System.Random(seed);
        Vector2[] octaveOffsets = new Vector2[octaves];
        for(int i=0;i<octaves;i++)
        {
            float offsetX = prng.Next(-100000, 100000) + offset.x;
            float offsetY = prng.Next(-100000, 100000) + offset.y;
            octaveOffsets[i] = new Vector2(offsetX, offsetY);
        }

        if(scale<=0)
        {
            scale = 0.0001f;
        }

        //返回的归一化处理
        float maxNoiseHeight = float.MinValue;
        float minNoiseHeight = float.MaxValue;

        //将噪声图的缩放设置在中心点上 计算e值是地图宽度的一半
        float halfwidth = mapWidth / 2f;
        float halfHeight = mapHeight / 2f;


        //对传入的函数的长、宽参数进行灰度值赋值 模拟噪声
        for (int y =0;y<mapHeight;y++)
        {
            for(int x=0;x<mapWidth;x++)
            {
                //频率和振幅
                float amplitude = 1;
                float frequency = 1;
                float noiseHeight = 0;

                for(int i =0;i<octaves;i++)
                {
                    //除以scale 让影响scale的同时能够影响到地图缩放的大小
                    float sampleX = (x-halfwidth) / scale *frequency +octaveOffsets[i].x;
                    float sampleY = (y-halfHeight)/ scale*frequency+octaveOffsets[i].y;
                    //柏林值 Mathf.PerlinNoise可以简单理解为随机获得在这个点的灰度值
                    float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;  //让噪声取值为-1到1的范围 让地形发生更多的变化 
                    //将灰度值返回给这个点
                    noiseMap[x, y] = perlinValue;
                    noiseHeight += perlinValue * amplitude;

                    amplitude *= persistance;
                    frequency *= lacunarity;
                }

                //获取噪声值的范围 便于后期归一化处理
                if(noiseHeight>maxNoiseHeight)
                {
                    maxNoiseHeight = noiseHeight;
                }
                else if(noiseHeight<minNoiseHeight)
                {
                    minNoiseHeight = noiseHeight;
                }

                //将高度应用于我们的噪声图 使坐标XY等于该噪声高度值
                noiseMap[x, y] = noiseHeight;
            }
        }

        //将取值限定 归一化处理
        for (int y = 0; y < mapHeight; y++)
        {
            for (int x = 0; x < mapWidth; x++)
            {
                noiseMap[x, y] = Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, noiseMap[x, y]);
            }
        }
                //返回噪声前对其进行归一化处理,使所有的值都回到0到1的范围内
                //跟踪噪声图中的最低值和最高值
                return noiseMap;
    }
}

二、地图生成器MapGenerator脚本的属性添加

很好理解,地图生成器是根据noise脚本为基础来创造噪声图的,noise脚本中修改的属性也要在这个脚本中进行更改

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

public class MapGenerator : MonoBehaviour
{
    public int mapWidth;
    public int mapHeight;
    public float noiseScale;

    public int octaves; //八度数量
    [Range(0,1)] //以滑块的形式限定范围
    public float persistance; //持久值
    public float lacunarity; //缺陷

    public int seed; //种子
    public Vector2 offset;  //偏移量
    
    public bool autoUpdate; //是否自动更行

    //生成地图
    public void GenerateMap()
    {
        //这里将输入的长、宽、大小代入刚刚定义好的生成噪声的函数中
        float[,] noiseMap = Noise.GenerateNoiseMap(mapWidth, mapHeight, seed,noiseScale,octaves,persistance,lacunarity,offset);

        //MapDisplay是用来将噪声转化为地形的脚本 在这里将上面处理后的数据转化为地形
        //下一个脚本再具体介绍 这里可以直接写
        MapDisplay display = FindObjectOfType<MapDisplay>();
        display.DrawNoiseMap(noiseMap);

    }
    private void OnValidate() //脚本中的数据改动时会自动调用
    {
    //将脚本中的值进行限定 因为超出这个值后没有意义
        if(mapWidth<1)
        {
            mapWidth = 1;
        }
        if(mapHeight<1)
        {
            mapHeight = 1;
        }
        if(lacunarity<1)
        {
            lacunarity = 1;
        }
        if(octaves<0)
        {
            octaves = 0;
        }

    }
}

三、最终的效果展示

保存脚本、之后我们就可以在Unity中运行查看效果了,对于不理解的新添属性值,我们可以在Unity的调试界面对这些属性值进行更改,看对于噪声图会发生怎样的变化
在这里插入图片描述
这样一个基本的用于控制地形生成的噪波图就制作好了,是不是很有趣呢?感兴趣的话点个关注,后面持续更新!

上期教程连接:Unity程序化地形教程 第一期 噪波图的制作

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;