Unity 随机 生成地形 (PerlinNoise 柏林噪声)

  • 程序化地图生成
    • 地图显示模块
    • 柏林噪声地图模块
      • 柏林噪声效果显示
    • 彩色地图模块
      • 色彩地图效果显示
    • 基础网格生成规则
    • 网格地图模块
      • 网格地图效果显示
    • 程序化地图管理模块
    • 地图管理 菜单编辑
    • 代码搭载
    • 效果展示

程序化地图生成

地图显示模块

三种不同的地图格式数据生成:DrawNoiseMap() 噪声地图DrawTexture() 色彩地图DrawMesh() 网格地图
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 地图显示
/// 将噪声贴图转换为纹理
/// </summary>
public class MapDisplay_ZH : MonoBehaviour
{[Header("纹理渲染")]public Renderer _TextureRender;[Header("网格数据")]public MeshFilter _MeshFilter;[Header("网格渲染")]public MeshRenderer _MeshRender;/// <summary>/// 噪声地图绘制/// </summary>/// <param 柏林噪声="_NoiseMap"></param>public void DrawNoiseMap(float[,] _NoiseMap){//地图宽度int _Width = _NoiseMap.GetLength(0);//地图高度int _Height = _NoiseMap.GetLength(1);//根据传入值  确定渲染纹理长宽Texture2D _Texture = new Texture2D(_Width, _Height);//获取噪波数组中的所有值Color[] _ColourMap = new Color[_Width * _Height];//设置每个像素点的颜色for (int y = 0; y < _Width; y++){for (int x = 0; x < _Height; x++){//色彩取样// Color 是一维数组 噪声是二维数组//获取当前像素点所在位置 : Y值 乘 地图宽度 再加上 X  就是当前像素在噪声地图中的位置//当前取样点的颜色 //由于只想要 黑白色域  所以使用 Color.black 和 Color.white_ColourMap[y * _Width + x] = Color.Lerp(Color.black, Color.white, _NoiseMap[x, y]);}}//色彩传递//纹理贴图赋值_Texture.SetPixels(_ColourMap);_Texture.Apply();//主纹理贴图赋值_TextureRender.sharedMaterial.mainTexture = _Texture;//地图大小赋值_TextureRender.transform.localScale = new Vector3(_Width, 1, _Height);}/// <summary>/// Texture 地图绘制/// </summary>/// <param 图像="_Texture"></param>public void DrawTexture(Texture2D _Texture){//渲染贴图赋予_TextureRender.sharedMaterial.mainTexture = _Texture;//渲染物体大小设置_TextureRender.transform.localScale = new Vector3(_Texture.width, 1, _Texture.height);}/// <summary>/// 网格地形绘制/// </summary>/// <param 地形网格="_MeshData"></param>/// <param 地形贴图="_Texture2D"></param>internal void DrawMesh(MeshData _MeshData, Texture2D _Texture2D){_MeshFilter.sharedMesh = _MeshData.CreteMesh();_MeshRender.sharedMaterial.mainTexture = _Texture2D;}
}

柏林噪声地图模块

这个模块为基础模块:返回值在0.0到1.0之间。(返回值可能略低于0.0或超过1.0。)关键性代码: Mathf.PerlinNoise()
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 柏林噪声地图生成
/// </summary>
public static class Noise_ZH
{/// <summary>/// 柏林噪声地图生成方法/// </summary>/// <param 地图宽度="_MapWidth"></param>/// <param 地图高度="_MapHeight"></param>/// <param 地图大小="_Scale"></param>/// <param 种子="_Seed"></param>/// <param 抵消="_Octaves"></param>/// <param 持续="_Persistance"></param>/// <param 空隙="_Lacunarity"></param>/// <param 偏移抵消="_Offset"></param>/// /// <returns></returns>public static float[,] GenerateNoiseMap(int _MapWidth, int _MapHeight, float _Scale, int _Seed, 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(-10000, 10000) + _Offset.x;float _OffsetY = _Prng.Next(-10000, 10000) + _Offset.y;_OctaveOffsets[i] = new Vector2(_OffsetX, _OffsetY);}//避免地图  不存在if (_Scale <= 0){_Scale = 0.0001f;}//地图放大响应float _HalfWidth = _MapWidth / 2;float _HalfHeight = _MapHeight / 2;//最大噪声高度float _MaxNoiseHeight = float.MinValue;//最小噪声高度float _MinNoiseHeight = float.MaxValue;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++){//地图单元取整float _SampleX = (x - _HalfWidth) / _Scale * _Frequency + _OctaveOffsets[i].x;float _SampleY = (y - _HalfHeight) / _Scale * _Frequency + _OctaveOffsets[i].y;//根据传入参数 生成2D柏林噪声float _PerlinValue = Mathf.PerlinNoise(_SampleX, _SampleY) * 2 - 1;//噪波高度等于 柏林噪声 乘于 振幅_NoiseHeight += _PerlinValue * _Amplitude;//振幅变更_Amplitude *= _Persistance;//频率变更_Frequency *= _Lacunarity;}//限值操作if (_NoiseHeight > _MaxNoiseHeight){_MaxNoiseHeight = _NoiseHeight;}else if (_NoiseHeight < _MinNoiseHeight){_MinNoiseHeight = _NoiseHeight;}//传入地图数据_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]);}}//返回地图数据return _NoiseMap;}}

柏林噪声效果显示

彩色地图模块

色彩地图模块:
TextureFromColourMap() 纹理生成模块
TextureFromHeightMap() 高度生成模块
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 纹理生成器
/// </summary>
public static class TextureGenerator_ZH
{/// <summary>/// 颜色地图的纹理/// </summary>/// <param 色彩地图="_ColourMap"></param>/// <param 宽度="_Width"></param>/// <param 高度="_Height"></param>/// <returns></returns>public static Texture2D TextureFromColourMap(Color[] _ColourMap, int _Width, int _Height){Texture2D _Texture = new Texture2D(_Width, _Height);//绘制模式 变更//点过滤-纹理像素变得块状近距离//边缘块状显示//_Texture.filterMode = FilterMode.Point;_Texture.filterMode = FilterMode.Point;//纹理坐标缠绕模式//将纹理夹紧到边缘的最后一个像素_Texture.wrapMode = TextureWrapMode.Clamp;//色彩传递//纹理贴图赋值_Texture.SetPixels(_ColourMap);//必须要应用一下不然不响应_Texture.Apply();return _Texture;}/// <summary>/// 高度贴图纹理/// </summary>/// <param 高度贴图="_HeightMap"></param>/// <returns></returns>public static Texture2D TextureFromHeightMap(float[,] _HeightMap){//地图宽度int _Width = _HeightMap.GetLength(0);//地图高度int _Height = _HeightMap.GetLength(1);根据传入值  确定渲染纹理长宽//Texture2D _Texture = new Texture2D(_Width, _Height);//获取噪波数组中的所有值Color[] _ColourMap = new Color[_Width * _Height];//设置每个像素点的颜色for (int y = 0; y < _Width; y++){for (int x = 0; x < _Height; x++){//色彩取样// Color 是一维数组 噪声是二维数组//获取当前像素点所在位置 : Y值 乘 地图宽度 再加上 X  就是当前像素在噪声地图中的位置//当前取样点的颜色 //由于只想要 黑白色域  所以使用 Color.black 和 Color.white_ColourMap[y * _Width + x] = Color.Lerp(Color.black, Color.white, _HeightMap[x, y]);}}色彩传递纹理贴图赋值//_Texture.SetPixels(_ColourMap);//_Texture.Apply();return TextureFromColourMap(_ColourMap, _Width, _Height);}
}

色彩地图效果显示

基础网格生成规则

当三角网格数据绘制顺序为逆时针时:
123、134  法线方向为朝上。
当三角网格数据绘制顺序为顺时针时:
143、132  法线方向为朝下

法线方向:法线(normal line),是指始终垂直于某平面的直线。在几何学中,法线指平面上垂直于曲线在某点的切线的一条线。法线也应用于光学的平面镜反射上。
如果法线方向背对视角方向,那么该网格三角面将不可视。

网格地图模块

网格地图模块:MeshData 网格类AddTrianle()为关键性方法进行三角形网格绘制逻辑CreteMesh() 网格数据填充方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 网格生成器
/// </summary>
public static class MeshGenerator_ZH
{/// <summary>/// 地形网格生成/// </summary>/// <param 高度地图="_HeightMap"></param>public static MeshData GenerateTerrainMesh(float[,] _HeightMap){//宽度int _Width = _HeightMap.GetLength(0);//高度int _Height = _HeightMap.GetLength(1);//网格划分float _TopLeftX = (_Width - 1) / -2f;float _TopLeftZ = (_Height - 1) / -2f;//网格数据MeshData _MeshData = new MeshData(_Width, _Height);//三角形 绘制序号int _VertexIndex = 0;//网格数据填充for (int y = 0; y < _Height; y++){for (int x = 0; x < _Width; x++){//顶点数据填充_MeshData._Vertices[_VertexIndex] = new Vector3(_TopLeftX + x, _HeightMap[x, y], _TopLeftZ + y);//UV 数据填充_MeshData._UVs[_VertexIndex] = new Vector2(x / (float)_Width, y / (float)_Height);//剔除 行 列 最边缘 的顶点  不计入网格渲染计算if (x < _Width - 1 && y < _Height - 1){_MeshData.AddTrianle(_VertexIndex, _VertexIndex + _Width + 1, _VertexIndex + _Width);_MeshData.AddTrianle(_VertexIndex + _Width + 1, _VertexIndex, _VertexIndex + 1);}//序号增加_VertexIndex++;}}return _MeshData;}
}/// <summary>
/// 网格数据
/// </summary>
public class MeshData
{//顶点数据public Vector3[] _Vertices;//绘制序列public int[] _Triangles;//UV 数据public Vector2[] _UVs;//三角 序号int _TriangleIndex;public MeshData(int _MeshWidth,int _MeshHeight){//网格顶点数据_Vertices = new Vector3[_MeshWidth * _MeshHeight];//UV 数据_UVs = new Vector2[_MeshWidth * _MeshHeight];//三角形绘制序列_Triangles = new int[(_MeshWidth - 1) * (_MeshHeight - 1) * 6];}/// <summary>/// 网格三角形绘制/// </summary>/// <param 顶点A="_A"></param>/// <param 顶点B="_B"></param>/// <param 顶点C="_C"></param>public void AddTrianle(int _A,int _B,int _C){//例如:// 1 2 3// 4 5 6// 7 8 9// 绘制 逻辑为  124 245 235 356 457 578 568 689  右手定则  逆时针 法线方向朝上//注意 绘制的的方向要统一   统一顺时针绘制  或者逆时针绘制_Triangles[_TriangleIndex] = _C;_Triangles[_TriangleIndex+1] = _B;_Triangles[_TriangleIndex+2] = _A;_TriangleIndex += 3;}/// <summary>/// 新建网格/// </summary>/// <returns></returns>public Mesh CreteMesh(){//网格数据Mesh _Mesh = new Mesh();//顶点数据赋予_Mesh.vertices = _Vertices;//三角形序列赋予_Mesh.triangles = _Triangles;//UV 数据 赋予_Mesh.uv = _UVs;//使用默认法线_Mesh.RecalculateNormals();//数据返回return _Mesh;}
}

网格地图效果显示

程序化地图管理模块

用作管理地图模块化生成
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
///  地图管理
/// </summary>
public class MapGenertor_ZH : MonoBehaviour
{/// <summary>/// 地图显示类型枚举/// </summary>public enum DrawMap { NoiseMap, ColourMap, MeshMap }[Header("地图绘制类型")]public DrawMap _DrawMap = DrawMap.NoiseMap;[Header("地图宽度")]public int _MapWidth;[Header("地图高度")]public int _MapHeight;[Header("地图大小")]public float _NoiseScale;[Header("八度")]public int _Octaves;[Header("持续")][Range(0, 1)]public float _Persistance;[Header("空隙")]public float _Lacunarity;[Header("地图种子")]public int _Seed;[Header("偏移")]public Vector2 _Offset;[Header("地形区域")]public TerrainType[] _Regions;[Header("自动更新布尔")]public bool _AutoUpdate;/// <summary>/// 地图生成 调用/// </summary>public void GenerateMap(){//参数传递 float[,] _NoiseMap = Noise_ZH.GenerateNoiseMap(_MapWidth, _MapHeight, _NoiseScale, _Seed, _Octaves, _Persistance, _Lacunarity, _Offset);//色彩地图Color[] _ColourMap = new Color[_MapWidth * _MapHeight];//根据地形高度进行色彩赋予for (int y = 0; y < _MapHeight; y++){for (int x = 0; x < _MapWidth; x++){//获取当前地图高度值float _CurrentHeight = _NoiseMap[x, y];//进行地形区域判定for (int i = 0; i < _Regions.Length; i++){if (_CurrentHeight <= _Regions[i]._Height){//色彩赋值_ColourMap[y * _MapWidth + x] = _Regions[i]._Colour;break;}}}}//查找 MapDisplay_ZH 搭载物体MapDisplay_ZH _Display = FindObjectOfType<MapDisplay_ZH>();//根据不同类型进行不同地图绘制if (_DrawMap == DrawMap.NoiseMap){//进行柏林噪声地形绘制_Display.DrawTexture(TextureGenerator_ZH.TextureFromHeightMap(_NoiseMap));}else if (_DrawMap == DrawMap.ColourMap){//进行色彩贴图地形绘制_Display.DrawTexture(TextureGenerator_ZH.TextureFromColourMap(_ColourMap, _MapWidth, _MapHeight));}else if (_DrawMap == DrawMap.MeshMap){//进行网格地形绘制_Display.DrawMesh(MeshGenerator_ZH.GenerateTerrainMesh(_NoiseMap), TextureGenerator_ZH.TextureFromColourMap(_ColourMap, _MapWidth, _MapHeight));}}/// <summary>/// 当脚本被加载或检查器在值被修改时调用此函数时(仅在编辑器调用中)/// </summary>private void OnValidate(){//保证初始化显示if (_MapWidth < 1){_MapWidth = 1;}if (_MapHeight < 1){_MapHeight = 1;}if (_Lacunarity < 1){_Lacunarity = 1;}if (_Octaves < 0){_Octaves = 0;}}
}//序列化
[System.Serializable]
/// <summary>
/// 地形类型
/// </summary>
public struct TerrainType
{//名称public string _Name;//高度public float _Height;//颜色public Color _Colour;
}

地图管理 菜单编辑

需要在 根目录创建一个 Editor 文件夹并把代码文件放进去才能执行
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
/// <summary>
/// 菜单编辑
/// </summary>
[CustomEditor(typeof(MapGenertor_ZH))]
public class MapGeneratorEditor_ZH : Editor
{public override void OnInspectorGUI(){MapGenertor_ZH _MapGen = (MapGenertor_ZH)target;//绘制内置检查器//如果发现变更if (DrawDefaultInspector()){//如果更新布尔为 Ture  就持续更新地图if (_MapGen._AutoUpdate){_MapGen.GenerateMap();}}//在 MapGenertor_ZH 上创建更新按钮if (GUILayout.Button("Generate")){_MapGen.GenerateMap();}}
}

代码搭载


效果展示

根据地图种子的值来进行地图随机变换



暂时先这样吧,如果有时间的话就会更新,实在看不明白就留言,看到我会回复的。
路漫漫其修远兮,与君共勉。

Unity 随机 生成地形 (PerlinNoise 柏林噪声)相关推荐

  1. Unity无限地形生成(基于柏林噪声的简单生成)

    Unity无限地形生成(基于柏林噪声的简单生成) 要求:构建一个户外开放世界游戏,为该游戏添加天空,地形,植物,并支持场景里自由漫游.这里实现一个无限地形的产生: 实现漫游 漫游的功能由玩家移动和摄像 ...

  2. Unity记录3.3-地图-柏林噪声生成 2D 地图

    文章首发及后续更新:https://mwhls.top/4486.html,无图/无目录/格式错误/更多相关请至首发页查看. 新的更新内容请到mwhls.top查看. 欢迎提出任何疑问及批评,非常感谢 ...

  3. Unity记录3.4-地图-柏林噪声生成 1D 地图及过渡地图

    文章首发及后续更新:https://mwhls.top/4489.html,无图/无目录/格式错误/更多相关请至首发页查看. 新的更新内容请到mwhls.top查看. 欢迎提出任何疑问及批评,非常感谢 ...

  4. [游戏随机生成地形] Meteorite Algorithm

    懒得不想复习: 今天在尝试生成随机地形的时候, 想到了一个简单又比较实用的方法, 不知道是否有前辈已经用过, 我暂且将它命名 Meteorite Algorithm (陨石算法) 从名字就能猜出来, ...

  5. unity3d 随机生成地形之随机山脉

    利用Fractal Noise生成地形,再加上山体shader,外加雪shader Noise生成结果 noise 生成主要参考这篇文章,就不再赘述 Value3D: Perlin2D: Fracta ...

  6. unity随机生成怪物(抽奖)代码

    我在网上发现居然找不到,都是转盘滚轮什么的抽奖,没有这种随机生成类似十连抽性质的代码 使用方法 SortedDictionary<string, int> monsterProb = ne ...

  7. MATLAB | MATLAB地形生成:矩形迭代法 · 傅里叶逆变换法 · 分形柏林噪声法

    1:矩形迭代法 这个非常简单,就是将矩阵的四个角分别定下初值,之后进行如下形式的迭代就好: [wxyz]⟶[ww+x2xw+y2w+x+y+z4x+z2yy+z2z]+noise.\begin{bma ...

  8. 木木的Unity学习笔记(四)—— Unity中的柏林噪声(Perlin Noise)

    木木的Unity学习笔记(四)-- Unity中的柏林噪声 柏林噪声是一个非常强大算法,经常用于程序生成随机内容,在游戏和其他像电影等多媒体领域广泛应用.算法发明者Ken Perlin也因此算法获得奥 ...

  9. html 生成image java makenoise,[图形学] 柏林噪声 (perlin noise)

    参考论文:<An Image Synthesizer> Ken Perlin 如果你是游戏玩家,你也许曾在游戏风景中驻足,并仔细观察草木和岩石的贴图,并感叹于它那看似杂乱而又自然的纹脉.你 ...

  10. unity柏林噪声生成2d随机地图

    1.说下思路.柏林噪声需要两个小于1的的参数导入.然后柏林噪声会输出一个相对波动变化的值0到1之间,如果对这个值进行的区间判断,就可以决定生成地图数量.比如,if<0.6再生成地图块, 2.对传 ...

最新文章

  1. Hibernate一级缓存
  2. 2017蓝桥杯 对局匹配(贪心)
  3. 大型网站技术架构文摘
  4. linux cgi命令,Linux之cgi实现系统主机监控
  5. php字符串中删除字符串函数,PHP 实现删除任意区间内字符串函数方法
  6. 漂亮的不太像手机!三星Galaxy S11最新渲染图曝光
  7. 【Flink】Flink CDH6.3.2 下的yarn per job模式 savepoint和checkpoint,卡住,没有保存成功文件
  8. Python模块学习 ---- zlib 数据压缩
  9. 关于信道利用率的总结与一道习题的最终解释
  10. MySQL 死锁专题问题处理
  11. 从开锁到中年危机的杂谈
  12. CAUSALITY FOR MACHINE LEARNING
  13. (一)市场调查大赛系列——市场调查研究选题
  14. 2021年中国非接触式传感设备市场趋势报告、技术动态创新及2027年市场预测
  15. 信号完整性之铜皮粗糙度
  16. OpenAI注册(ChatGPT)
  17. MFC修改界面图标时,已导入.ico文件,但是程序运行后,界面不显示更新后的新图标
  18. iOS weak和assign修饰OC对象的区别
  19. 2022年K1刷第三方固件教程
  20. 原神最新版本MMD模型官方下载网站

热门文章

  1. 新手必学:美术基础理论知识---透视篇
  2. python分析为啥没有本山大叔,不算春晚!
  3. 网络攻击防范(SQL注入、XSS、CSRF、DDos)
  4. matlab控制器参数整定方法
  5. 以下不是python语言合法命名的是_以下不是Python语言合法命名的是:???????????????????????????????...
  6. leetcode: super washing machines
  7. Windows10蓝屏的解决办法
  8. mc服务器删除玩家信息,mc服务器删除玩家
  9. Android学习笔记:自定义View之手写签名
  10. 2012结束单身,与TA的婚礼你选哪?