您现在的位置是:主页 > news > 凉山建设局网站/网站建设与维护
凉山建设局网站/网站建设与维护
admin2025/4/24 9:39:28【news】
简介凉山建设局网站,网站建设与维护,网页制作教程古诗词,教育部国家中职示范校建设网站Unity程序化地形教程 第一期 前言:最近在准备作品集,想吧Blender里面利用shader实现的程序化地形导入Unity中,发现我弄不了,于是转向了直接在Unity中实现程序化地形的新途径,但是网上的教程很少,b站和CSDN…
Unity程序化地形教程 第一期
前言:最近在准备作品集,想吧Blender里面利用shader实现的程序化地形导入Unity中,发现我弄不了,于是转向了直接在Unity中实现程序化地形的新途径,但是网上的教程很少,b站和CSDN好像都没有详细的教程,所以今天我科学上网找了一下,查到了一个16年的程序化视频教学,自带机翻英文的那种,就是按他的翻译根本翻译不对,听也听不太懂,所幸能够理解代码意思,想借这个机会去做一篇程序化地形的教程,先是以博客的形式去记录每次所学,把所学弄懂,再去下一章的学习,最后我会在b站制作一个视频教程,希望大家多多支持,文章是我学习后自己的理解,肯定有些地方不对,不对的地方还请大家多多指教,感兴趣的朋友可以点一波关注,持续更新!
零、学完本期后的效果展示
初步直租出一张噪声图,为后续创作打下基础
一、我对于程序化地形的理解
简单来说程序化地形需要一个高效的伪随机数生成器,随机数包括地形的长、宽、高度、大小,然后利用一个载体把这些数合理的展示出来,大家最常见的其实就是黑白噪声图
以这张图为载体,他的长、宽、大小就是程序化地形的大小,那么有人就会问:地形高度和地形间的间隙是如何表现出来的?这里其实是使用到了噪声的波形来做的
波形图看起来是不是很像山脉的起伏一样?从而我们可以自己定义一个波形图,通过修改波形图的长宽大小,以及噪声的分布来实现一个地形的设计,这样之后噪声图就相当于一个地形编辑器了,我们通过编辑噪声图间接的编辑出地形,进而我们再加上颜色和其他属性,就能为地形增添上更多的细节,以此来达到一个程序化地形的效果。
二、程序化地形初步实现
1.定义噪声图
首先我们需要像我上面所说的一样,定义一个噪声图,让它成为程序化地形的一个载体,为此我们编写一个噪声脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public static class Noise
{ //定义一个函数生成地图 利用噪声来设置地形的长宽大小等属性public static float[,] GenerateNoiseMap(int mapWidth,int mapHeight,float scale) {//定义一个两个维度的浮点数类型的数组 用于存储长、宽数据float[,] noiseMap = new float[mapWidth, mapHeight];//防止地图的大小出现负数if(scale<=0){scale = 0.0001f;}//对传入的函数的长、宽参数进行灰度值赋值 模拟噪声for(int y =0;y<mapHeight;y++){for(int x=0;x<mapWidth;x++){//除以scale 让影响scale的同时能够影响到地图缩放的大小float sampleX = x / scale;float sampleY = y / scale;//柏林值 Mathf.PerlinNoise可以简单理解为随机获得在这个点的灰度值float perlinValue = Mathf.PerlinNoise(sampleX, sampleY);//将灰度值返回给这个点noiseMap[x, y] = perlinValue;}}return noiseMap;}
}
2.定义一个地形生成器
在这里就会用到我们刚刚写好的noise脚本,用这个脚本来实现对噪声参数传入的控制,用这个脚本来控制地形的生成
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MapGenerator : MonoBehaviour
{public int mapWidth;public int mapHeight;public float noiseScale;//生成地图public void GenerateMap(){//这里将输入的长、宽、大小代入刚刚定义好的生成噪声的函数中float[,] noiseMap = Noise.GenerateNoiseMap(mapWidth, mapHeight, noiseScale);//MapDisplay是用来将噪声转化为地形的脚本 在这里将上面处理后的数据转化为地形//下一个脚本再具体介绍 这里可以直接写MapDisplay display = FindObjectOfType<MapDisplay>();display.DrawNoiseMap(noiseMap);}
}
3.定义一个地图展示器
将我们所输入的参数得到的噪声图转换为一个地图展现出来
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MapDisplay : MonoBehaviour
{//通过控制plan的Renderer来控制地形的显示public Renderer textureRender;//绘制噪声图public void DrawNoiseMap(float[,] noiseMap){//用来获取数组指定维数中的元素个数 这里分别是长和宽int width = noiseMap.GetLength(0);int height = noiseMap.GetLength(1);Texture2D texture = new Texture2D(width, height);//Color类型是接收的是一个[0,1]的值,需要用R,G,B,A四个值各自除以255//这里是定义整张图的取值面积 即要修改颜色点的多少Color[] colourMap = new Color[width * height];//将每个点赋值色彩for(int y=0;y<height;y++){for(int x =0;x<width;x++){colourMap[y * width + x] = Color.Lerp(Color.black, Color.white, noiseMap[x, y]);}}//将图按原比例绘制下来texture.SetPixels(colourMap);//将定义的图像纹理进行应用 此前需要进行SetPixelstexture.Apply();//将应用后的图交给Randerer去展现效果textureRender.sharedMaterial.mainTexture = texture;textureRender.transform.localScale = new Vector3(width, 1, height);}
}
四、定义一个地图编辑器
用于实时呈现出更改后的地形的样式
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;//将我们定义好的控件展示出来
[CustomEditor(typeof(MapGenerator))]
public class MapGeneratorEditor : Editor
{public bool mapGenChange = true;public override void OnInspectorGUI() {MapGenerator mapGen = (MapGenerator)target;//修改参数不用运行就能看到修改后的效果if(DrawDefaultInspector()){if(mapGenChange){mapGen.GenerateMap();}}//点击按键就能更新if (GUILayout.Button("Generate")){mapGen.GenerateMap();}}
}
5.初步效果展现
首先在3D场景中创建一个Plane,只保留如下两个组件
创建一个材质球,将它的类型修改为Unlit/Texture,并赋值给Plane,如上图所示
再新建一个空物体用来控制地形的生成,挂载脚本以及赋值如图所示
最后我们通过修改Map Genertor脚本中的参数来控制地形的生成
这样一个基本的用于控制地形生成的噪波图就制作好了,是不是很有趣呢?感兴趣的话点个关注,后面持续更新!