Unity 随机 生成地形 (PerlinNoise 柏林噪声)
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 柏林噪声)相关推荐
- Unity无限地形生成(基于柏林噪声的简单生成)
Unity无限地形生成(基于柏林噪声的简单生成) 要求:构建一个户外开放世界游戏,为该游戏添加天空,地形,植物,并支持场景里自由漫游.这里实现一个无限地形的产生: 实现漫游 漫游的功能由玩家移动和摄像 ...
- Unity记录3.3-地图-柏林噪声生成 2D 地图
文章首发及后续更新:https://mwhls.top/4486.html,无图/无目录/格式错误/更多相关请至首发页查看. 新的更新内容请到mwhls.top查看. 欢迎提出任何疑问及批评,非常感谢 ...
- Unity记录3.4-地图-柏林噪声生成 1D 地图及过渡地图
文章首发及后续更新:https://mwhls.top/4489.html,无图/无目录/格式错误/更多相关请至首发页查看. 新的更新内容请到mwhls.top查看. 欢迎提出任何疑问及批评,非常感谢 ...
- [游戏随机生成地形] Meteorite Algorithm
懒得不想复习: 今天在尝试生成随机地形的时候, 想到了一个简单又比较实用的方法, 不知道是否有前辈已经用过, 我暂且将它命名 Meteorite Algorithm (陨石算法) 从名字就能猜出来, ...
- unity3d 随机生成地形之随机山脉
利用Fractal Noise生成地形,再加上山体shader,外加雪shader Noise生成结果 noise 生成主要参考这篇文章,就不再赘述 Value3D: Perlin2D: Fracta ...
- unity随机生成怪物(抽奖)代码
我在网上发现居然找不到,都是转盘滚轮什么的抽奖,没有这种随机生成类似十连抽性质的代码 使用方法 SortedDictionary<string, int> monsterProb = ne ...
- MATLAB | MATLAB地形生成:矩形迭代法 · 傅里叶逆变换法 · 分形柏林噪声法
1:矩形迭代法 这个非常简单,就是将矩阵的四个角分别定下初值,之后进行如下形式的迭代就好: [wxyz]⟶[ww+x2xw+y2w+x+y+z4x+z2yy+z2z]+noise.\begin{bma ...
- 木木的Unity学习笔记(四)—— Unity中的柏林噪声(Perlin Noise)
木木的Unity学习笔记(四)-- Unity中的柏林噪声 柏林噪声是一个非常强大算法,经常用于程序生成随机内容,在游戏和其他像电影等多媒体领域广泛应用.算法发明者Ken Perlin也因此算法获得奥 ...
- html 生成image java makenoise,[图形学] 柏林噪声 (perlin noise)
参考论文:<An Image Synthesizer> Ken Perlin 如果你是游戏玩家,你也许曾在游戏风景中驻足,并仔细观察草木和岩石的贴图,并感叹于它那看似杂乱而又自然的纹脉.你 ...
- unity柏林噪声生成2d随机地图
1.说下思路.柏林噪声需要两个小于1的的参数导入.然后柏林噪声会输出一个相对波动变化的值0到1之间,如果对这个值进行的区间判断,就可以决定生成地图数量.比如,if<0.6再生成地图块, 2.对传 ...
最新文章
- Hibernate一级缓存
- 2017蓝桥杯 对局匹配(贪心)
- 大型网站技术架构文摘
- linux cgi命令,Linux之cgi实现系统主机监控
- php字符串中删除字符串函数,PHP 实现删除任意区间内字符串函数方法
- 漂亮的不太像手机!三星Galaxy S11最新渲染图曝光
- 【Flink】Flink CDH6.3.2 下的yarn per job模式 savepoint和checkpoint,卡住,没有保存成功文件
- Python模块学习 ---- zlib 数据压缩
- 关于信道利用率的总结与一道习题的最终解释
- MySQL 死锁专题问题处理
- 从开锁到中年危机的杂谈
- CAUSALITY FOR MACHINE LEARNING
- (一)市场调查大赛系列——市场调查研究选题
- 2021年中国非接触式传感设备市场趋势报告、技术动态创新及2027年市场预测
- 信号完整性之铜皮粗糙度
- OpenAI注册(ChatGPT)
- MFC修改界面图标时,已导入.ico文件,但是程序运行后,界面不显示更新后的新图标
- iOS weak和assign修饰OC对象的区别
- 2022年K1刷第三方固件教程
- 原神最新版本MMD模型官方下载网站
热门文章
- 新手必学:美术基础理论知识---透视篇
- python分析为啥没有本山大叔,不算春晚!
- 网络攻击防范(SQL注入、XSS、CSRF、DDos)
- matlab控制器参数整定方法
- 以下不是python语言合法命名的是_以下不是Python语言合法命名的是:???????????????????????????????...
- leetcode: super washing machines
- Windows10蓝屏的解决办法
- mc服务器删除玩家信息,mc服务器删除玩家
- Android学习笔记:自定义View之手写签名
- 2012结束单身,与TA的婚礼你选哪?