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

柏林噪声是一个非常强大算法,经常用于程序生成随机内容,在游戏和其他像电影等多媒体领域广泛应用。算法发明者Ken Perlin也因此算法获得奥斯卡科技成果奖。在游戏开发领域,柏林噪声可以用于生成波形,起伏不平的材质或者纹理。例如,它能用于程序生成地形(例如使用柏林噪声来生成我的世界(Minecraft)里的地形),火焰燃烧特效,水和云等等。柏林噪声绝大部分应用在2维,3维层面上,但某种意义上也能拓展到4维。柏林噪声在1维层面上可用于卷轴地形、模拟手绘线条等。
在Unity中,Unity为我们提供了柏林噪声的方法,但只支持2维层面,方法如下:

// 在Mathf类中,调用方法为Mathf.PerlinNoise(x, y);
public static float PerlinNoise(float x, float y);

参数x和y为柏林噪声采样的2维坐标点的x和y,返回值为0.0 ~ 1.0之间的小数。但是有一点需要注意,在Unity中,柏林噪声可能会生成略大于1.0的小数,如果返回值0.0 ~ 1.0对开发者很重要,那么需要限定一下返回值。并且在每次传入的参数固定相同时,柏林噪声会返回同样的返回值,例如:

private void Update()
{float result = Mathf.PerlinNoise(5.0f, 5.0f); Debug.Log(result);  // 你会发现在Console中输出的值都是一样的
}

接下来,在Unity中实际操作一下。

模拟生成石头纹理

在Unity中新建场景,在场景中添加一个Cube,编写脚本并绑定给Cube,脚本如下:

using System;
using UnityEngine;namespace Com.PerlinNoise.Fumiki
{public class RockMaterialMonitor : MonoBehaviour{/// <summary>/// 图片的宽度/// </summary>[SerializeField] private int pictureWidth = 100;/// <summary>/// 图片的高度/// </summary>[SerializeField] private int pictrueHeight = 100;/// <summary>/// 用于柏林噪声的X采样偏移量(仿伪随机)/// </summary>[SerializeField] private float xOrg = .0f;/// <summary>/// 用于柏林噪声的Y采样偏移量(仿伪随机)/// </summary>[SerializeField] private float yOrg = .0f;/// <summary>/// 柏林噪声的缩放值(值越大,柏林噪声计算越密集)/// </summary>[SerializeField] private float scale = 20.0f;/// <summary>/// 最终生成的柏林噪声图/// </summary>private Texture2D noiseTex;/// <summary>/// 颜色数组/// </summary>private Color[] pix;/// <summary>/// 方块的材质/// </summary>private MeshRenderer meshRend;private void Start(){meshRend = GetComponent<MeshRenderer>();noiseTex = new Texture2D(pictureWidth, pictrueHeight);// 根据图片的宽高填充颜色数组pix = new Color[noiseTex.width * noiseTex.height];// 将生成的柏林噪声图赋值给方块的材质meshRend.material.mainTexture = noiseTex;}private void Update(){// 计算柏林噪声CalcNoise();}/// <summary>/// 计算柏林噪声/// </summary>private void CalcNoise(){float y = .0f;while (y < noiseTex.height){float x = .0f;while (x < noiseTex.width){// 计算出X的采样值float xCoord = xOrg + x / noiseTex.width * scale;// 计算出Y的采样值float yCoord = yOrg + y / noiseTex.height * scale;// 用计算出的采样值计算柏林噪声float sample = Mathf.PerlinNoise(xCoord, yCoord);// 填充颜色数组pix[Convert.ToInt32(y * noiseTex.width + x)] = new Color(sample, sample, sample);x++;}y++;}noiseTex.SetPixels(pix);noiseTex.Apply();}       }
}

效果图:

运行游戏后,在Cube的Inspector面板上分别拖动脚本中的X Org,Y Org和Scale可以看到材质的变化:

模拟我的世界(Minecraft)生成地形

在Unity中新建场景,并创建一个空的GameObject,我命名为WorldRoot,编写脚本并绑定给WorldRoot,脚本如下:

using UnityEngine;namespace Com.PerlinNoise.Fumiki
{public class MapCreator : MonoBehaviour{/// <summary>/// 用以柏林噪声采样的X和Z值(柏林噪声返回的是Y值)/// </summary>private float seedX, seedZ;/// <summary>/// 地图的宽度(X轴方向)/// </summary>[SerializeField] private int width = 50;/// <summary>/// 地图的深度(Z轴方向)/// </summary>[SerializeField] private int depth = 50;/// <summary>/// 地图的最大高度/// </summary>[SerializeField] private int maxHeight = 10;/// <summary>/// 决定了采样间隔 值越大 采样间隔越小/// </summary>[SerializeField] private float relief = 15.0f;private void Awake(){seedX = Random.value * 100f;seedZ = Random.value * 100f;for (int x = 0; x < width; x++){for (int z = 0; z < depth; z++){GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);cube.transform.localPosition = new Vector3(x, 0, z);cube.transform.SetParent(transform);SetY(cube);}}}private void OnValidate(){if (!Application.isPlaying)return;foreach (Transform child in transform)SetY(child.gameObject);}/// <summary>/// 利用柏林噪声设定Y值/// </summary>/// <param name="cube"> 需要被设定Y值的物体 </param>private void SetY(GameObject cube){float y = 0;float xSample = (cube.transform.localPosition.x + seedX) / relief;float zSample = (cube.transform.localPosition.z + seedZ) / relief;float noise = Mathf.PerlinNoise(xSample, zSample);y = maxHeight * noise;// 为了模仿我的世界的格子风 将每一次计算出来的浮点数值转换到整数值y = Mathf.Round(y);cube.transform.localPosition = new Vector3(cube.transform.localPosition.x, y, cube.transform.localPosition.z);Color color = Color.black;if (y > maxHeight * 0.3f){ColorUtility.TryParseHtmlString("#019540FF", out color);}else if (y > maxHeight * 0.2f){ColorUtility.TryParseHtmlString("#2432ADFF", out color);}else if (y > maxHeight * 0.1f){ColorUtility.TryParseHtmlString("#D4500EFF", out color);}cube.GetComponent<MeshRenderer>().material.color = color;}}
}

运行后效果如下:

同前面的石头纹理,运行后选中WorldRoot,在Inspector面板分别拖动MaxHeight或Relief会对地形产生一定的影响,效果如下:

在正版的我的世界中,制作人也是使用的柏林噪声生成地形,是不是跃跃欲试了呢,快去试试这个新奇的东西吧。

木木的Unity学习笔记(四)—— Unity中的柏林噪声(Perlin Noise)相关推荐

  1. [Unity学习笔记]2D游戏中的触碰/OnMouseDown

    [Unity学习笔记]2D游戏中的触碰/OnMouseDown 这种情况多用于2D游戏的触屏 1.给2D游戏对象加上collider 2D,让其能够被检测到

  2. 【Unity学习笔记】[Unity中文课堂教程] C#中级编程代码

    [Unity学习笔记][Unity中文课堂教程] C#中级编程代码 最近想补一补C#基础,Unity官方的C#中级编程教程质量很高,于是开个帖子把跟着敲+记录了部分价讲解和我自己的理解的代码存在这 原 ...

  3. Unity学习笔记:Unity 3D 飞机大战

    Unity学习笔记:Unity 3D 飞机大战 1.打开unity软件后,首先新建Quad作为背景,导入飞机模型,并为其添加刚体 然后创建C#脚本,挂载到飞机上. 2.给飞机创建子弹,让子弹成为预制体 ...

  4. 【Unity学习笔记】Unity中的欧拉角(Euler Angle)和万向节(Gimbal)

    声明:此篇文章是个人学习笔记,并非教程,所以内容可能不够严谨.可作参考,但不保证绝对正确.如果你发现我的文章有什么错误,非常欢迎指正,谢谢哦. 目录 1 奇怪的现象 1.2现象一 1.2 现象二 1. ...

  5. Unity学习笔记:unity介绍(一)

    一.Unity是什么? 1.Unity发音[ˈjuːnəti] 2.俗称有U3D,Unity3D.unity 3.Unity开发商是美国的Unity公司,成立于2004年,位于美国旧金山. 4.uni ...

  6. Unity 使用柏林噪声(Perlin Noise)生成网格地图

    前言 最近在尝试制作一个基于网格地图的RPG游戏,所以想着自己生成一个网格地图. 但是网格地图的生成有很多的方式,大多数的方式都达不到我的要求,我需要一个地图可以随机生成各种地形,也可以储存一些地形数 ...

  7. Unity学习笔记5 unity的js转c#

    上一篇已经说过,unity的js是一种变种的js,和真正的js还是有区别的,所以有时候会给人一种有点不伦不类的感觉--如果对于完全没有编程基础的人来说,建议一开始就直接学c#吧,不要浪费时间去学js. ...

  8. Unity学习笔记 关于Unity相机的FOV以及水平FOV和垂直FOV之间的转换

    前言 关于FOV FOV 是在任何给定时间通过人眼.相机取景器或在显示屏上可见的可观察世界的范围.它指的是整个区域的覆盖范围,而不是单个固定焦点.FOV 还描述了一个人可以看到可见世界的角度. FOV ...

  9. Unity学习笔记(8) Unity残影效果整理,3D、2D、通用方案

    Unity做残影效果是个不难的工作. 但是一些细节会对使用方法产生限制,这里整理一下各种情况下推荐的残影效果实现方案 1.3D网格 (高性能) 2.2D人物 (非骨骼动画) (高性能) 3.其它场景 ...

  10. 【theano-windows】学习笔记四——theano中的条件语句

    前言 按照官网教程,学习条件语句Switch和ifelse的使用 参考地址: conditions 性能对比 ifElse是将布尔变量和两个变量当做输入 Switch是将张量和两个变量当做输入. 因为 ...

最新文章

  1. python graphics画圆_求高手解答·· graphics画圆出现报错!
  2. 不错!基于Springboot 2.0 + LayUI开发的物流管理系统(已开源)
  3. GitHub地图转误差坐标
  4. MySQL之终端(转载笔记)
  5. 光流 | HS光流算法与LK光流算法(基于OpenCV)
  6. 设计模式的理解:组合模式 (Composite)
  7. 怎样用MATLAB画二次函数曲线,MATLAB 二次函数的画图.doc
  8. Kotlin 的 Array 转 List
  9. 学python开发必须要会wsgi么_python Web开发你要理解的WSGI uwsgi详解
  10. [转载]windows2003上IIS+PyISAPIe1.1..0部署成功
  11. 检测 USB 设备拨插的 C# 类库:USBClassLibrary
  12. AI 新基建怎么做,腾讯云正式公布全景布局
  13. am335x linux修改ip,Linux 修改代码以支持LED 控制(board-am335xevm)
  14. 计算机网络管理员高级操作技能考核试卷,计算机网络管理员(高级)操作技能试题样题(2)...
  15. mysql 分析函数 平均_mysql平均函数
  16. 图书管理系统(图书类)
  17. CSS盒子模式之四 - 绝对定位和相对定位
  18. C#中操作IIS 7.0
  19. 自学shell编程——第1讲(基础概念、变量、符号、字符串处理)
  20. 华汇超市二层的小餐馆可当MBA案例了

热门文章

  1. 2010年考研数学一解析
  2. Java实现支付宝当面付(扫码)详细步骤
  3. 高铁没票也能上车?揭秘黄牛是如何做到的
  4. 【刷题】【LCA】小仓鼠找糖
  5. manjaro终端terminal提示bash: export: `=‘: not a valid identifier
  6. DeepStream系列之SDK文件夹解析
  7. Android Google推荐的图片加载库Glide介绍
  8. 【分享】身为一个资深的“收藏程序猿”必须知道的一些网址(建议收藏)
  9. 第一站 杭州--西湖龙井
  10. 软件测试(二)-经典测试技术-静态测试