OMO萌 - Unity 3D教程心得
type: channel
link: https://omo.moe/category/Unity-3D/
description: Unity 3D游戏制作方面的心得体会
items: 【3ds max入门教程】Unity游戏模型制作之草丛的搭建——第三节: 3ds max模型设计从简到繁
items: 【3ds max入门教程】Unity游戏模型制作之草丛的搭建——第二节: Photoshop平面地图布局设计
items: 【3ds max入门教程】Unity游戏模型制作之草丛的搭建——第一节:3ds max一些初始推荐设置
items: Let's build an indie game!《吾王大战全明星》独立游戏设计制作日记 Chapter 1 - 初章: 项目回顾和重启
items: Let's build an indie game!《吾王大战全明星》独立游戏设计制作日记 Chapter 0 - 序章
items: Substance Painter入门学习阶段效果
items: 【Unity 3D进阶教程分享】EndlessTerrain无限地形搭建 第十节：LOD结合视距分区块mesh地形渲染
items: 【Unity 3D进阶教程分享】EndlessTerrain无限地形搭建 第九节：多线程同步协调处理多区块思想和基本实现
items: 【Unity 3D进阶教程分享】EndlessTerrain无限地形搭建 第八节：多区块地形生成与隐藏
items: 【Unity 3D进阶教程分享】EndlessTerrain无限地形搭建 第七节：LOD多细节层次渲染功能实现

【3ds max入门教程】Unity游戏模型制作之草丛的搭建——第三节: 3ds max模型设计从简到繁
type: item
date: 2021-04-28T15:10:00+00:00
description: 第三节3ds max模型设计从简到繁上一节：[post cid="876"cover="http://"/]我们入门先设计一些简单的模型1.草丛的模型制作1.a. 草的制作做一个竖直的圆柱体，高5段，面1，边环6段即可调整尺寸至高30cm，半径2cm左右即可。R键调整形状scale，变成扁平。然后转为editable poly形状按自己喜好调整，这里先调整叶子中部两条竖直控制线靠近中部：v+f或者F键获得前视角镜头，然后选择顶点模式，框中中间两排所有顶点，Alt+X透视模式查看背面顶点是否选中，如果你开启了右侧菜单selection的Ignore backfacing背面忽略，建议取消勾选，或者通过旋转后按住ctrl选中背面的顶点都行，此刻注意Selection菜单提示24 Verticaes Selected辅助确认已选中的顶点个数。然后点击右侧菜单Edit Geometry项目里Constraints约束选项，选中Edge按边约束，然后R键就可以调整顶点往中间移动了，获得合适位置后，Constraints约束选中默认的None，继续调整顶点位置获得合适的叶面厚度Editable Poly选中模式(selection)切换为Edge，通过swift loop增加竖直居中环绕线圈控制叶脉，再选择叶面的两条控制线稍微凸出（注意正反两面都操作一次），获得叶片基本形状，或者调整两侧叶脉线凹进也可，自己灵活调整。Editable Poly选中模式(selection)切换到Polygon面模式，选中上下面删除。Editable Poly选中模式(selection)切换到Vertex(顶点)，选中顶部的顶点，通过R键调整到扁平贴合，点击上方菜单weld合并多余顶点，如果合并范围出现异常，点击weld右侧设置箭头，调整合适的weld范围即可。weld完毕后测试点是否成功合并，尤其新手，如果你的weld范围设置过小，可能部分顶点并未成功合并。（我们这里的草宽度设置的2cm，而weld阈值默认是10cm，一般来说是无需手动调整范围）草的模型调整满意后，切换vertex为选择Editable Poly,我们开始快速展UV map，选中右侧modifier list的UVW map编辑器，如果你之前按我推荐的增加了修改器列表快捷按钮，只需要点击一下即可。然后V-F选择正面视角方便快速匹配UV，mapping参数选中planar（平面），点击view Align,使得展uv的平面与当前front视角一致，然后再点fit部署拓展到整个叶面，collapse all，保存当前uvw map配置，就算完成展uv了点击M打开材质编辑器，我们为这根草快速添加材质，这里演示下用基本渐变色彩（gradient）示意材质分布：展开Blinn basic parameter（明暗器基本参数栏目）这些参数里面一般常用的就是ambient(环境光） , diffuse（漫反射）和specular（高光），其中diffuse漫反射通常用来选择贴图材质，物体表面漫反射效果是最主要的材质表现通道，我们一般经常在diffuse设置里选择基本色或者bitmap材质位图，给模型赋予基本的皮肤而其他的参数主要用来模拟真实环境一些物理现象，让三维物体表现更加自然用的。如果你的材质编辑器不是我这样的，可以选择Modes >compact material editor即可，任意右键一个材质格子即可选择材质格子分布尺寸3x2，5x3，6x4，或者点击编辑器右边的齿轮按钮，在设置里选择需要的排版大致介绍下，入门阶段大致了解下即可，因为材质编辑器是最常用也最容易熟悉的模块，不用刻意记忆接下来我们修改diffuse参数，选择漫反射材质为Gradient，用基本调色盘渐变色来赋予草材质贴图。如果你嫌颜色梯度不够用，可以选择Grandient Ramp范围，自由增加控制点Gradient Type和Interpolation选择linear线性过渡即可，如果你想要卡通效果，interpolation过渡效果选择Solid固定色即可，角度Coordinates选择VW方向，因为这里我们颜色是竖直方向过渡，具体方向按自己的模型需求更换。然后点击Assign material to selection ，Show shaded materials in view point ,应用，这样我们就能看到渲染后的效果了。我们的草算是基本完成了，接下来自行发挥调整尺寸和色彩，做一些基础草的变种，为我们的草丛构建提供一些基础素材。如果你想要添加材质，可以自己拍照或者网络找非商业素材，加工获得贴图导入，另外，我们也可以通过substance designer制作材质，为模型赋予更加真实细腻的材质效果，当然一般情况下…

【3ds max入门教程】Unity游戏模型制作之草丛的搭建——第二节: Photoshop平面地图布局设计
type: item
date: 2021-04-28T14:56:00+00:00
description: 第二节 Photoshop地图设计流程上一节：[post cid="868" cover="http://"/]根据我们设计的原画布局(个人练手仅供参考，节约时间，草图一枚)，绘制对应的平面地图场景创建一个4096x4096的项目Shift+Ctrl+N新建一个4096x4096的地图map图层1.a. 参考方块图案制作在地图图层上方直接ctrl+shfit+N新建一个grey mask遮罩图层再文件菜单>>新建一个256x256画布，利用铅笔工具，选择画笔>>旧版画笔>>方头画笔>>任意硬边方形画笔，设置像素大小为128，ctrl+R调出刻度尺，拖拽横竖两条参考线均分画布四等分，shift用1像素硬笔圆画上蓝色垂线，左侧菜单油漆桶工具G将右上和左下选择深灰色50%涂抹，右下和左上选择较浅灰色25%涂抹，，编辑菜单>定义图案，命名Grid回到地图画布，选择grey mask遮罩图层，shift+F5填充，选择图案，找到刚才新建的图案，确定。如果不喜欢这种明暗相间的方块图案，我们可以直接做128x128、64x64规格的纯格子图案画布，仅用1像素铅笔工具填充左下角两边深黑色，中间填一个浅灰单色即可1.b. 再次新建图层Land Sketch绘制陆地草图，同时新建Sea图层，等待绘制海洋区域Land Sketch主要将城堡和河流以及城墙，森林的位置摆放调整大致位置,简图只是用来整体分布定位，免得出现模型尺寸严重不协调的问题，具体布局后期会按需随时调整，不需要多精准的位置分布。1.c. 然后制作Icons Mask 深灰遮罩和Icons图层（所有icons放置在Icons Mask遮罩范围内，以区分图例和地图范围），绘制填入相关的图例。1.d. 简单比例尺的制作使用矩形选框工具（M),样式：固定大小，设置像素128x6，然后新建Scale图层到Land Sketch图层上方，合适位置放置此选区，然后编辑菜单>描边>居中描边1个像素，鼠标拖动选区平移到右侧贴紧此描边，再次编辑菜单>填充黑色，以此类推，做出4段比例尺效果即可，然后上方T键输入刻度16，32，48，64，单位为米（4096/128=32格子，我们稍后unity内地形尺寸设置为512unit，即512/32=16米/unit，所以每段比例尺代表距离是16米）Ctrl+G新建Labels组管理所有图标文字，Scale Unit组管理比例尺Scale图层和相关文字刻度基本地形位置绘制完毕，输出地图草图然后Unity内新建cube，scale修改为512，0.1，512，命名Base Terrian，position改成256，0，256，让terrian的左下角对齐原点然后新建cube，scale改为1，2，1，位置归零后改为0，1.05，0，命名Character，选中角色状态下，f键聚焦，平移到合适镜头位置，选中Main Camera物体后，在GameObject菜单，Align with view对齐当前game视角为镜头视角选择game视图，比例16：9，调整合适镜头位置后观察实际游戏效果布局感觉，再对Land Sketch地图布局新建大致尺寸的城堡方块，炮塔方块，河流模型，进行位置放置调整，检查布局和比例合适后，挂载一个fpscontroller丢到player内，设置position归零，测试看看效果就可以开始正式进入建模阶段，开始按着清单搭建模型了下一节：[post cid="880" cover="http://"/]

【3ds max入门教程】Unity游戏模型制作之草丛的搭建——第一节:3ds max一些初始推荐设置
type: item
date: 2021-04-26T07:47:00+00:00
description: 草丛，碎石，天空几乎是游戏场景中必有的元素，作为入门初级阶段的学习目标，从草丛的制作入手，是个理想的选择，一套不错的草丛贴图，可以显著改善游戏场景表现，而草丛的优化处理也是提高游戏帧数的必修课程，那么，闲话少说，我们直接开始吧！第一节 3ds max一些初始推荐设置每个人都有自己偏好的3ds max个性设置，那么作为入门第一阶段，我在此分享下个人比较推荐的常用设置，尤其是游戏制作通用的一些设置，可以方便你的制作和后期修正一、网格和对齐设置：Tools>Grids and Snaps>Grid and Snap Settings ,Snaps选择中一般我们勾选Grid Points（网格点） 和Vertex（顶点），在执行模型对齐操作方面会比较方便准确Options选择Enable Axis Constraints(启动轴向约束),对于Display rubber band(显示移动路径)，按个人喜好选择是否开启Home Grid选项中将Grid Spacing（网格步进/间距）改成100.0cm，即一个标准米间距，作为人物和普通地形常见参考单位，对于我们游戏场景制作比较合适二、单位度量设置打开Customize>Units setup,显示单位设置度量单位为Centimeters即1个厘米，然后System Unit Setup选择1meter作为1个单位，这样3ds max默认一个单位长度就是1米了，这样方便我们模型在unity里面的显示。三、缩放可视范围调整默认缩放观察范围是有一定限制的，我们调整为最大，将我们Perspective 视图Alt+W或者点击右下角放大到最大，然后选择Perspective视角菜单，下拉Viewpoint Clipping，这样右侧就会出现一个竖直的范围区间，将最小和最大约束小三角标调整到上下极限范围即可四、常用视角快捷键Alt+X 透视显示F3，F4：网格，面框渲染和默认渲染视图切换Ctrl+R或者Alt+鼠标中键，旋转轨道视角查看，我们可以按U或者P键切换正交Orthographic或者透视Perspective模式。鼠标中键按住拖拽即可进入平面视角Pan查看Customize>Hotkey Editor修改快捷键，个人喜欢将重做设置为和ps一致的Ctrl+Alt+ZAlt+滚轮：慢速缩放Ctrl+滚轮：快速缩放ctrl+Alt+按住鼠标中键平移鼠标：无限制缩放z建快速聚集已选择物体Alt+q快速隐藏所有未选中物体，聚焦当前模型2020版本更改清单参考：3ds max 2020键位更新五、自定义修改器列表快捷按钮点击屏幕右侧Modify修改菜单，看到修改器列表Modifier List右键，设置Modifiers sets 配置：我们在弹出的配置窗口为自定义配置命名，比如my set然后Total Buttons按钮增加到12个，按键盘对应字母可以快速浏览左侧清单首字母修改器我个人常用修改器list供参考：Mesh Select UVW Map Unwrap UVW TurboSmooth FFD 2x2x2 FFD 3x3x3FFD 4x4x4 FFD(box) Chamfer（切角，倒角） Spherify（球体化） Tessellate（细化） EditPoly然后Save，再点OK退出。如果按钮列表未显示，右键Modifiers list选择显示按钮Show Buttons即可类似的，我们点击最右边这个工具扳手按钮，也可以设置自定义的快捷按钮，比如增加一个UVW Remove按钮，方便今后清除不需要的材质效果如果你对3ds max不太熟悉，可以去customize>>preferences首选项，修改General常规选项的scence undo次数默认20为50或者更多，不过注意内存占用也会随之增加。六. 创建参考方块新建一个box，选择Modify修改长宽高为100cm，获得一个标准立方，w选择移动模式，直接在下方菜单修改位置起点为原点（0，0，0)修改物体名称为Scale_Box,颜色自己选择喜欢的，然后File菜单保存为Scale_Box_One_Uint即可。我们回到Unity，导入看看效果七、Unity基本设置我们从Unity官方下载Unity hub管理包，安装需要的版本，学习用可以用最新的，稳定生产建议用LTS（Long Term Support）稳定版本，打开Unity我们在Asset文件夹下新建Meshes文件夹，存放我们的基础原型模型，从3ds max的max文件拖拽进即可，然后展开我们的模型图标，选择No Name材质文件，右键Extract from prefab释放到Assets>Materials文件夹下或者你喜欢的目录，这样我们就可以修改预制体模型的…

Let's build an indie game!《吾王大战全明星》独立游戏设计制作日记 Chapter 1 - 初章: 项目回顾和重启
type: item
date: 2021-04-24T07:57:00+00:00
description: [post cid="853" cover="http://"/]初章 回顾和重启《吾王大战全明星》独立游戏设计制作日记Chapter 1 at 24th Apri , 2021.琐事耽搁，项目重启进度如意料般延后，抽空抓紧时间布局第一阶段的项目目标第一个场景，主菜单界面敲定需要制作的基本模型和场景清单将核心模型和可重复利用的模型作为优先制作目标，整理列表如下：参看原画设计的第一关序幕设计内容，我们将需要制作的模型列出清单如下（按类别和复杂程度排列）类别一般包括：天空盒，地形，地表植被，环境装饰物品，道具，互动道具，焦点物品，粒子特效清单有助于时间安排和对场景的理解，查漏补缺，正规制作流程必备环节。[collapse status="false" title="模型清单列表"]编号模型名称所属类别备注白盒阶段高模阶段贴图阶段1天空盒天空盒unity内制作，昏黄战场风格 2主地形地形unity内制作，平原，海岸线 3悬崖地形预制体，按距离远近布局多个 4海洋地形 5河流地形 6树木1环境装饰 7树木2环境装饰 8树木3环境装饰 9横木环境装饰 10枯树枝环境装饰 11草类1（短）地表植被 12草类2（中）地表植被 13草类3（长）地表植被 14灌木1环境装饰 15灌木2环境装饰 16灌木3环境装饰 17花丛1地表植被 18花丛2地表植被 19花丛3地表植被 20小碎石环境装饰 21石块环境装饰 22大块石头环境装饰 23高坚果城墙道具（动画） 24bilibili地雷道具（动画） 25土豆地雷道具（动画） 26达柯鸭炮台道具（动画） 27二战飞机焦点道具（动画） 28飞鸟轰炸机道具（动画） 29武装坦克焦点道具（动画） 30桥梁道具（动画） 31天线宝宝1道具（动画） 32天线宝宝2道具（动画） 33天线宝宝3道具（动画） 34草泥马道具（动画）参考照片 35士兵道具（动画）暂未定下原型 36城门焦点道具 37建筑1（方形）焦点道具 38建筑2（尖塔）焦点道具 39建筑3（方形高塔）焦点道具 40主城（宝石核心）焦点道具 41太阳环境装饰血红色 42云层粒子效果黑色调，搭配红色晕染 43枪口火焰1粒子效果飞机类 44枪口火焰2粒子效果炮台类 45枪口火焰3粒子效果坦克类 46火堆粒子效果战火场景烘托 47烟尘粒子效果战场气氛烘托 48河水shader增加场景动感 49海洋shader映衬天空的战火 [/collapse]清单整理完毕，最重要的思考就是如何将以上物件高效优美地制作出来从理性和科学角度出发，之前的顺序是比较合理的：草丛>>花朵>>灌木>>树枝>>树丛为一个系列，小碎石>>石块>>大块石头也是不错的顺序建筑、动物、水域和各种天空盒，特效为其他类型，除了水域和天空盒在技术和重复利用方面有一定价值，建筑和动物等互动道具优先度不高，排为最低顺序基本安排完毕，接下来就是思考可能出现的难点和进度拖延点:①从树枝到树木的建模，这个过程是比较耗时的，需要注意；②草泥马，天线宝宝这种带头部的生物建模，技术要求比较高，在模型制作中，可能会占用大量时间，以及产生挫败感；③飞机坦克等hard surface机械建模，可能需要大量的icon和贴图，才能加速制作过程，对于精度控制，需要一定的经验，容易陷入追求精致的无底洞；④天空盒具体细分需要精力了解细节，敲定合适的精度和技术层次需要一定的学习时间和技术要求；⑤枪口火焰和烟尘视觉效果制作，需要进一步学习完善，可能会占用大量时间；⑥场景牵扯到一些基本的动作制作和动画曲线，需要大量的温习回顾时间熟悉上手。精简难点为：枯燥的建模过程，生物/脸部建模难度挑战，硬面机械建模技术，基本动作设计重拾信心建立节点：①草丛花木基本环境搭建完成；②碎石石块布局完善；③基本建筑外形加入；④土豆地雷，可达鸭等简单互动道具建模完毕；⑤枪口特效简单实现并部署⑥水面简单shader实现并部署时间花费计划：草丛建模制作约2-3天，开始阶段重温3ds max需要额外时间，给自己一个缓冲；花朵建模需要约1-2天；灌木建模制作约1-2天，做成树木，需要额外2-3天时间；碎石和石块制作约1-2天；①草丛花木基本环境搭建完成 此节点完成需要6-10天；②碎石石块布局完善 此节点完成需要1-2天；结合以往经验，后续时间安排心中有大致了解即可，先完成本月内可预见目标吧,后续进度更新中...

Let's build an indie game!《吾王大战全明星》独立游戏设计制作日记 Chapter 0 - 序章
type: item
date: 2021-04-04T04:47:00+00:00
description: 序章 梦想的起点《吾王大战全明星》独立游戏设计制作日记Start from 3rd Apri , 2021.做出属于自己的独立游戏，一直以来都是很多玩家的梦想吧！将梦想变成现实，是很多人追寻的目标，甚至是人生的意义所在。很多人倒在了半路，很多人转型。这是个美好又显得幼稚的话题，不过想做的话，一步步先走下去，做出个再丑再有bug的东西，也算是梦实现的第一步吧。Part 1.取舍有限的时间和对品质的追求，高级技能学习和自身能力水准，都是相互制约，充满矛盾的，平衡与取舍是非常重要的一步，这是我在过去三年摸爬滚打中得出的最重要的经验，这种矛盾在三A大厂甚至整个业界都是很难处理的一个痛点。如何确定价值点和降低品质?谈到游戏制作，相信很多人都擅长列举出价值点：浅显的来说，有人在意好玩（游戏性），有人在意代入感（设计、渲染等），有人在意画面（次世代高精度贴图，高模设计），有人在意策略性（数值策划，关卡设计），从入门萌新到业界精英，讨论游戏的价值点亮点，都可以娓娓道来，那么为什么这么多人最终失败？当然，市场营销和资金成本是很重要的一环，那么分析许多拥有一个良好的运营团队和较充裕的资金支持环境的制作公司，依然会有很多的游戏口碑收益双双暴雷，那么，决定一个游戏好坏/成功的本质，并不见得是闪光点不够，不好玩。这是个空泛和缺乏说服力的论点，仅仅是一些个人心得感悟记录，从我个人喜欢玩的游戏来分析，我对游戏制作成功有一些自己的看法：游戏玩法：新手最大的失策，就是认为随着时代的发展，新制作的游戏，肯定比旧的优秀，新时代的人类，探讨研究出来的玩法，肯定比老游戏完善，我认为，这是非常错误的。流传下来的玩法，才是最值得保留融入的游戏玩法核心。这不是守旧，也不是大型团队不敢创新的借口，哪怕现代好玩的开放游戏代表如《我的世界》《泰拉瑞亚》，看似创新，实际内核是人类玩泥巴的天性。又如策略、对抗类游戏经典，其实象棋围棋军旗这种实体游戏老古董玩法机制才是老祖。一些新近冒出的独立小游戏的成功和爆火，实际上玩法类似甚至同样玩法的游戏，早在黑白机时代各种暴雷游戏或者沉寂在历史洪流中无数小游戏中早已开发出来过。甚至同时代同类产品有很多，但是却“莫名其妙”失败。游戏面对的是人，而不是数据/机器这是我一直的坚持，诚然市场导向，金钱至上的环境，会让各种数据分析，人类心理研究肆无忌惮占据市场，玩弄玩家，让玩家不得不边骂边掏钱。是的，它们是成功的，胜者为王。但是任何市场需要多样化，无论人类社会组成，还是大自然的生物环境，这也是我坚持做一个独立小游戏的信心所在。游戏，一直伴随着人类文明的成长，人类对游戏的喜爱和探索，决定游戏行业是一个有价值，可贵的研究领域。尤其是男人对于游戏的追逐不亚于女人对于包包的渴望，哪怕再多再好的三A游戏诞生，依然满足不了玩家对于心目中游戏的渴望，男人（当然女人也一样）总觉得自己最想要的游戏是下一款。欲望和需求是市场的根本动力，所以，制作游戏是一门古老而持久的行业，不用担心落伍和衰败。而在各种大厂夹缝中生存的独立游戏开发来说，不用太在意盈利指标和用人成本（用爱发电甚至不需要多少工资），玩家对产品的可接纳宽容度，都是优势。其实无论是玩游戏还是开发游戏，本身都应该起源人类本性对于美好的事物的追寻，无论是开发者，还是玩家，本身其实是一类人。看起来很矛盾很奇怪的观点，是吧？这方面的成功典范，就是很多人熟悉的valve公司，也是我挺喜欢的一家游戏制作公司因为它做到了：我做了一些好玩的东西，邀请大家一起来玩。是的，游戏的玩法核心，本该如此简单朴实无华。此类游戏代表，很多就是开放类生存种田游戏，然后就是v社为代表的--游戏做好了，玩家来做mod。大师或者核心玩家用比较专业的技术构建出比较好玩的游戏规则，大家玩家一起来玩，听取玩家意见，改善规则，让强有力的规则和模式支撑玩家实现更多的可能，这就能成功。当然，这类游戏，对于新入行的开发者来说，挺难的，不光是技术，主要是经验眼光积累和时间消耗非常大，所以可以作为今后的理想，但是对于新人，我建议舍弃直接开发此类游戏，因为好酒需要时间沉淀，游戏亦然，新人开发自由世界，很容易只剩下空洞和单调；所以，独立小游戏，真的需要做小一点，价值点少一点，多舍弃一点。是的，为什么那么多人做游戏，无论独立游戏还是开发公司，很多都失败，是他们想要实现的闪光点太多了并不是闪光点多不好，而是小型团队很难支撑面面俱到，而更多情况下是，一款游戏只可能适合一类人群，普通团队很难作出来人人都喜欢，老少通吃类似自由世界探索类型的游戏。钻石不需要绚丽的色彩，也不需要玫瑰的芬芳。所以，在你想做一个自己的游戏之前，夸夸其谈，洋洋洒洒策划部署了天花乱坠的可玩性亮点吊炸天的设计和剧本之后，我真心地建议你，一步步砍掉所有的价值点闪光点，最后只留下一个核心，这个东西就是支撑你这个小游戏，让…

Substance Painter入门学习阶段效果
type: item
date: 2019-01-13T08:33:00+00:00
description: 第一节 Substance painter基础应用第一部分，一些简单的桌椅材质添加，substance painter最常用的layer（层）和mask（遮罩）以及generator（生成器）搭配brushes（笔刷）和alpha（透明通道）还有material（材质，智能材质等）组合操作得到以下效果：第二节 自定义材质的获取和加工第一部分，通过日常照片或者不规则尺寸贴图作为参考，在ps里制作修正为2048x2048标准2k尺寸贴图 转换为 转换为 转换为 通过位移+1024像素点进行tile map边界衔接处理，为了兼容性和质量建议保存为tga文件格式第二部分，在bitmap2material软件中，将上述标准尺寸位图转换为material材质图，我们需要输出四张图，一个base color基准颜色贴图，一个根据基础颜色贴图生成的normal map法线贴图，一个roughness map粗糙度贴图，还有一个ambient occlusion环境光遮蔽图调整流程基本逻辑为：output 微调选项中，先关闭所有项目，只选择base color，调整defuse|light微选项，light cancellation等降低光线效果，同时调整各种档位阴影，总之目的还原纯粹颜色贴图，排除掉环境阴影光线影响，得到纯粹的颜色材质。base color设置完毕，再到output微调选项中开启normal法线，如果是深色砖头，系统会自动将暗处处理为凹进，所以如果效果和自己感受的不太一样，也就是深色区域过多，而实际你需要这些区域显示凸起法线效果的话，去Global微选项下，选择invert relief即反转表面浮雕纹理方向，达到较为合适的凸起效果output 微选项下开启roughness，然后对粗糙度微选项进行设置output 微选项下开启ambient occlusion，对环境光遮蔽进行设置，如果阴影太黑，在AO平衡中，将对应Low Mid High频率进行负值降低效果，达到满意为止，最后可以在2d视图依次查看四种贴图效果，查看无误后，选择全局2048x2048分辨率后输出改命名为Room_Wall_%U这种格式，将自动输出对应用途的四种贴图命名，方便管理之后依次修正ceiling和floor，得到三套，总共12张成品材质贴图第三部分 导入材质贴图到substance painter进行加工，添加display渲染项目ambinet occlusion,对三个面进行渲染，将三套材质放到一个方块上进行调整方便获得整体协调色彩和质感导入对应贴图到渲染后的项目，获得正确的初始状态如图：第三节 substance painter内材质的加工和完善使用立方体进行多个材质加工，为了直观和整体的色调统一墙壁增加一些喷漆条纹，增加fill layer添加black mask，在mask上增加fill layer，绘制dirt效果，多个dirt效果可以在一个层，改对应内部fill layer效果为exclusion模式，防止覆盖最下方fill layer 效果，达到叠加多样化效果的目的，在地板的加工中，可以多设置几个污渍叠加fill layer，对单个mask做到多个fill 效果叠加还可以使用智能fill layer，对条纹进行dirt风化效果实现地板的话，主要使用多个fill layer对 black mask进行蒙版加工，注意位于结构栏上方的fill layer选择渲染模式为exclusion，layer都是从最底部的绘制，逐个往上运算。外部主fill layer颜色可以微调为暗黄，作为污渍主体色调，可以在mask内部处理完毕后随时调整最终效果，依据素材色调酌情考虑新建外部主fill layer进行暗色mask处理天花板这里过于亮白，加入暗色fill layer和一层fill layer+black mask，针对mask增添fill layer进行暗色污渍处理，与之前的主fill layer 暗色mask叠加达到理想效果最后输出，记得分辨率2048x2048，文件格式tga，unity5 metallic默认设置即可第四节 材质导入unity做好屋子模型，增添对应三个材质球，将导入的三套总共9张材质贴图对应赋予到材质球上，屋子的基本效果就出来了，细节问题，之后再更新第五节 opacity透明材质加工和projection投射decal贴纸实现以透明塑料袋为例我们开始渲染贴图时，为了获得opacity贴图，在添加ambient occlusion环境光遮蔽贴图项之后，还需要新增加opacity贴图，小材质导入的时候选择1024分辨率即可，显示选项可以显示网格，作为小材质，渲染时可以选择将低精度模型作为高精度模型处理渲染完毕，开始加工：搜索shar…

【Unity 3D进阶教程分享】EndlessTerrain无限地形搭建 第十节：LOD结合视距分区块mesh地形渲染
type: item
date: 2018-12-25T18:11:00+00:00
description: 第十节 LOD结合视距分区块mesh地形渲染上一篇：[post cid="406" /]这一节我们将对不同视距的区块地形进行不同精度LOD区分绘制mesh网格首先我们需要新建一个类，来管理不同精细度的LOD mesh,针对每一个地形区块，获取其对应精度的mesh打开EndlessTerrain脚本：在EndlessTerrain类里面，最后新建：class LODMesh { public Mesh mesh; public bool hasRequestedMesh;//追踪是否已经请求mesh状态 public bool hasMesh; int lod;//当前mesh对应lod档位 public LODMesh(int lod) { this.lod = lod; } void OnMeshDataReceived(MeshData meshData)//②再处理收到mesh数据进行mesh生成，调整状态为true { mesh = meshData.CreateMesh(); hasMesh = true; } public void RequestMesh(MapData mapData)//①，先请求mesh，标记已请求状态，传入对应多线程方法 { hasRequestedMesh = true; mapGenerator.RequestMeshData(mapData, OnMeshDataReceived); } }我们再回到MapGenerator脚本，因为刚才在EndlessTerrain脚本新设置了LOD mesh对应功能而我们MapGenerator脚本也有个levelOfDetail变量，这个是用来管理DrawMapInEditor里面的LOD档位的，我们为了区分两者用途，将原来的levelOfDetal ctrl+r+r重命名为：PreviewLODInEditor，代表这个LOD属于编辑器界面预览LOD效果用的LOD，这样，我们在MapGenerator里面的RequestMeshData方法里请求传入 int lod，就不会弄混淆了，同样的，MeshDataThread方法中也增加此参数传入：int lod，再检查下，RequestMeshData方法里调用了MeshDataThread，这里也要加入 int lod参数，同时将里面调用的MeshDataThread也传入 lod参数，最后，我们检查下MeshDataThread方法，我们这个方法现在是专用来获取不同视距区块不同mesh精度用，上一节为了测试多线程通信，我们简单的对默认的LOD进行接收运算mesh，也就是现在的 PreviewLODInEditor，现在我们不再需要复制PreviewLODInEditor进行处理运算了，我们在这节的主要目的，就是要将所有多线程处理的mesh，改为基于新的lod判断分块体系，获取对应精度lod，再进行处理对应精细度的mesh数据，而不是之前的和PreviewLODInEditor每块地形都是一模一样的mesh精度，于是这里PreviewLODInEditor也要改成 lod。同样的，上节为了测试，与MapGenerator脚本对应的EndlessTerrain脚本中，我们在这里的OnMapDataReceived方法里面，请求执行RequestMeshData方法这句也可以暂时注释掉，稍等我们这节完善新的功能，同样的，OnMeshDataReceived方法暂时也不需要了，我们选中，Ctrl+K+C也全部注释掉，这节稍后我们会重新编写新的。将EndlessTerrain最后方RequestMeshData方法，中间也新增传入 lod参数这样，我们的 lod参数添加已经改造完毕，接下来接着我们在EndlessTerrain脚本需要新建一个结构体，用来管理不同LOD信息，属于哪档LOD，存储对应档位LOD精度，等等信息，方便调取，那么在脚本最后，新建结构体：public struct LODInfo{ public int lod； public float visibleDistThreshold；//可视距离阈值，用来对区块进行距离判定，对不同视距区块划分不同LOD精度，而不仅仅是固定的450视距了为了方便在面板调整视距阈值档位，我们加上 [System.Serializable]修饰，方便我们修改脚本最前方新加入数组：public LODInfo[] detailLevels;保存，来到Unity，去MapGenerator脚本开始手动设置我们LODInfo先将size设为3，来三档视野阈值看看Lod分别设为，0，1，2，VisibleDistThreshold设为200，400，600看看再回…

【Unity 3D进阶教程分享】EndlessTerrain无限地形搭建 第九节：多线程同步协调处理多区块思想和基本实现
type: item
date: 2018-12-25T17:54:00+00:00
description: 第九节 多线程同步协调处理多区块思想和基本实现上一篇：[post cid="403" /]这节我们将继续上节的无限地形生成功能完善，将上节制作出来的视野内三维plane的显示和隐藏功能与我们的MapGenerator相结合，这里将会用到多线程技术，之前我们第一节了解过协程的原理，这里多线程技术比协程更高级一些，这算是真正的多个线程都在一起跑，而不是协程的跳来跳去，适合处理一些短时间内计算量很大，任务数量较多，可以同步单独运算，同时又追求高效完成需要快速拿到多个运算结果的事情。由于Unity系统限制，实际上我们unity本身是没有多线程的，我们的副线程是干不了前台的画面渲染，人物运动，物理碰撞，AI运算这些涉及到Unity SDK或者说继承于Monobehaviour的一些操作的，这些只能交给主线程，但是，这不代表多线程没有用，后台的数据运算，比如说伤害计算，MeshData数据构建，网络交互更新，一些复杂的I/O调取操作，都是可以通过分配给副线程去做的，多线程是c#里实现的，可以辅助unity达到多线程的效果，通过Action和Callback之类的指令，和unity主线程交互，决定下一步的运算或者释放。多线程运算，涉及到的核心主要有两点，首先，unity主线程和其他C#副线程的交互，是一个重点，这个交互思想代码模板需要熟悉；其次，对于任务和计算的分配，这个优先级和排序，也是一个重点，否则大家一起抢着干同一件事情，造成数据混乱，显然是帮倒忙，也是不可取的；这一节，主要涉及到线程间交互方式，基本框架的构建和熟悉，这一块基本上都是标准模板，初学复杂，熟练后都是套路，代码看起来多，实际都是固定格式，不用害怕。对于任务优先级排序，我们稍微了解下入门级的五个优先级排序，和Lock指令锁定分配任务和分派线程，今后有时间的话再聊聊Loom指令委托到主线程上进行调度，差不多就可以实现一些基础的多线程操作了，更复杂的，慢慢来，多线程就像一把封印的神器，需要不断积累经验，解封用法，才会用的更加强大。好了，我们正式开始：在多线程编写前，我们需要打扫下之前的代码，MapGenerator脚本，我们GenerateMap方法里MapDisplay display三种drawMode方式判断和执行，算是一个单独的方法，我们为了今后不断扩充的系统考虑，将方法细分独立出来，目前考虑将这三种生成渲染模式放置到Inspector面板方便调试，我们可以在此脚本新建一个方法：public void DrawMapInEditor（）{ 复制所有Display代码到这里接下来，我们需要从GenerateMap方法中调用相应的Map数据，之前我们display这块代码和地图信息数组在同一个方法里，是可以直接调取GenerateNoiseMap里面这些地图数据的，现在分家了，在其他方法里调用另一个方法里的数据，是需要一个载体存储对应数据，再调用载体，读取数据，这也是基本的编程思想于是我们在脚本最后新建地图数据结构体：public struct MapData{ public float[,] heightMap;//灰阶高度图是二维数据，需要二维数组存储宽度和高度数据 public Color[] colourMap;//彩色图是整个色彩像素点数据，一维数组就可以存储Ctrl+.或者 Alt+Enter，快捷键构建结构体内部数据，勾选刚才新建的两个数据类型，然后确定就可以快速初始化了，//(如果后期不需要修改地图数据，可以将结构体内部所有元素加入readonly关键词)接下来我们在GenerateMap方法中返回MapData类型数据，void改成MapData同时别忘记在方法里，最后返回对应数据类型：return new MapData（noiseMap，colourMap）;这样，我们就可以通过MapData载体，在我们的DrawMapInEditor方法中调取需要的地图类型和对应数据了，在DrawMapInEditor方法里，开头申明赋值，准备调用：MapData mapData=GenerateMap（）;然后我们将noiseMap，colourMap修正为现在的 mapData.heightMap,mapData.colourMap，结构体内对应map类型，就可以进行绘制渲染了如果之前没有手动换行的话，一个快捷键组合：Ctrl+E+W，让系统自动换行，避免页面外的信息遗漏，忘记修改这么修改后，我们的GenerateMap就单独负责地图信息生成了，而与外部交流沟通数据，就交给我们新建的DrawMapInEditor方法了，于是我们可以考虑将 public MapData GenerateMap方法改为private，因为暂时不需要用来外部类调用它了，去掉publi…

【Unity 3D进阶教程分享】EndlessTerrain无限地形搭建 第八节：多区块地形生成与隐藏
type: item
date: 2018-12-25T17:43:00+00:00
description: 第八节 多区块地形生成与隐藏上一篇：[post cid="400" /]新建EndlessTerrain脚本public const float maxViewDistance=450; public Transform viewer; public static Vector2 viewerPosition; int blockSize; int blocksVisibleInViewDistance;上一节我们说到实际渲染的mesh网格是地图尺寸-1，我们为多区块地形的每个地形单元新定义变量名blockSize，下面在开始方法中进行赋值：void Start(){ blockSize=MapGenerator.mapBlockSize-1; blocksVisibleInViewDistance=Mathf.RoundToInt(maxViewDistance/blockSize); }接下来我们需要更新可见区块，那么继续构建相应的方法：每个mesh区块240尺寸，我们viewer位置设为（0，0）mesh原点的话，左侧block就是（-240，0），右下角的block就是（240，-240），那么最大视距除以每个block尺寸取整后，在区块坐标来说，左侧block就可以设为（-1，0），右侧就是（1，0），右下角的block所属区块坐标就是（1，-1）这个规则弄明白后，我们继续构建更新可视区块方法： void UpdateVisibleBlocks() { int currentBlockCoordinateX = Mathf.RoundToInt(viewerPosition.x / blockSize); int currentBlockCoordinateY = Mathf.RoundToInt(viewerPosition.y / blockSize); //求出当前区块x，y坐标值，使用取整方法 //通过遍历正负两个方向最大可视区块坐标范围，给所有视野内区块赋值对应坐标位置。 for (int yOffset = -blocksVisibleInViewDistance; yOffset <= blocksVisibleInViewDistance; yOffset++) { for (int xOffset = -blocksVisibleInViewDistance; xOffset <= blocksVisibleInViewDistance; xOffset++) { Vector2 viewedBlockCoordinate = new Vector2(currentBlockCoordinateX + xOffset, currentBlockCoordinateY + yOffset); } } } 接下来，我们就可以实例化这些block区块了，但是实例化之前，我们需要一个数据集合来存储这些坐标值和对应 地形区块信息，因为需要一个值存储坐标一个存储地形区块信息，那么 Dictionary字典是比较合适的，key键存储坐标信息，对应value值指向地形区块信息，这样到时候就可以记录所有地形，以免重复生成或者漏掉。创建字典之前，我们对所有地形区块创建一个类来表示：在我们的EndlessTerrain类里面，后面新建一个public class TerrainBlock{ }然后调用Dictionary数据集合类型需要用到using System.Collections.Generic;//默认已有则不用添加EndlessTerrian方法中新增字典：Dictionary<Vector2, TerrainBlock> terrainBlockDictionary = new Dictionary<Vector2, TerrainBlock>();再来到下方UpdateVisibleBlocks方法if (terrainBlockDictionary.ContainsKey(viewedBlockCoordinate)) { //稍后进行存储调取操作 } else { terrainBlockDictionary.Add(viewedBlockCoordinate, new TerrainBlock()); }//如果不存在，则将符合要求的block和对应坐标存储进字典保存我们再思考下public class TerrainBlock{这个类，当前需要通过一个空物体或者说mesh管理器之类的东西，生成对应block的mesh载体plane，最后再和我们的MapGenerator脚本交互，进行block生成功能实现。于是我们开始构建TerrianBlock类的构造函数：public class Terrai…

【Unity 3D进阶教程分享】EndlessTerrain无限地形搭建 第七节：LOD多细节层次渲染功能实现
type: item
date: 2018-12-25T17:28:00+00:00
description: 第七节 LOD多细节层次渲染功能实现上一篇：[post cid="394" /]我们继续上节内容，如何将平面plane mesh网格拉高形成立体网格，这需要新增变量，高度倍数，打开MeshGenerator脚本，GenerateTerrainMesh方法传入新增 float heightMultiplier方法内获取meshData.vertices顶点信息时将y轴信息加上加倍系数heightMap[x,y]乘上刚才新增的 heightMultiplier然后打开MapGenerator脚本,新增同样的加倍因子public float meshHeightMultiplier;在下方display drawMode里面display.DrawMesh(MeshGenerator.GenerateTerrainMesh方法里传入meshHeightMultiplier保存，然后点击MapGenerator物体，inspector面板可以看到咱们的MeshHeightMultiplier系数出来了，调整数值大小可以看见我们的mesh网格就随之起伏了，通过观察可以发现，水域地形也随着起伏剧烈，这和自然环境不太相符，我们应该分区域调整multiplier系数影响比例，水域范围起伏波动应该缓和一些这样我们可以通过加入一条变化曲线（curve）来模拟。打开MapGenerator脚本public AnimationCurve meshHeightCurve;回到unity，我们应该可以在inspector面板看到我们的curve选项了，打开curve选择第三条曲线，0.4这里右键设置新的拐点然后回到脚本，display.DrawMesh方法里，传入的GenerateTerrainMesh方法新增传入一个meshHeightCurve参数MeshGenerator脚本里面对应方法同样也要加入此参数传入：AnimationCurve heightCurve，然后在此方法里进行实现，原来的meshData.vertices获取数值，y轴存储的是 heightMap[x,y]信息，现在要将传入的heightCure曲线信息约束咱们的 heightMap[x,y]后的值存储为y轴数值，于是改此信息为：heightCurve.Evaluate(heightMap[x,y])*heightMultiplierheightCurve.Evaluate就是求出对应括号内位置curve曲线对应该点的数值，再加成高度倍数就拿到了更自然的高度倍数因子了保存，回到unity，点击generate看看效果，若不满意可以微调我们的曲线，达到满意的表现立体拉升效果实现完毕，接下来我们优化下多块地形细节渲染分层，为后面的无限地形生成奠定基础。这里用到的LOD技术，在游戏领域应用非常广泛，我们通过修改不同视野范围的三维模型mesh网格数，来降低系统渲染负荷，优化游戏体验，对远处或者不太容易关注到的模型降低细节表现来获得帧数的提升我们先解释下实现mesh分层的原理之前我们的meshGenerator脚本，存储mesh顶点信息的时候，用到的遍历累加是for (int x=0;x<width,x ++){//创建顶点}那么假设我们width是9，从0~8一共9个点，当index每次累加1的时候，将会逐步累加存储从0-8总共8个顶点信息和对应三角面那么如果我们index遍历规则改为i=2，跳过相邻点，则会存储五个点信息如果i=4，则会存储三个点信息当i=3这种情况，我们会发现需要第十个不存在的点来存储，这明显是不可取的，所以这就是细节划分的限制：简单来说，我们需要找一个公因数，即LOD分层index累加数值和我们地图width宽度值，两者公有的因数我们的演示体现了index和vertices顶点数关系，i=1，vertices个数为9i=2，vertices个数为5i=4，vertices个数为3我们需要找到通用的关系式i=1，v=ii=2，我们观察左边4条曲线代表四个循环，都是被i=2切分后分成了4条，每段记录一个顶点我们可以尝试将总宽度减掉最右边的1个，再除以i=2，获得左边所有切分后记录的顶点数，再补上最右边的点+1，公式可以是 vertices=[(width-1)/i]+1i=4 时候，我们验证下，减去最右侧终点一个后，除以跳跃值i=4，获得2个循环分块，每个分块存储1个顶点信息，最后加上最右侧的终点，结果是3个，和实际相符。公式是可用的下面解释下为何不超过65000个顶点数：一般的，我们 vertices=width*height对于方形地图 vertice=width^2v<=255^2(65025)本来实际限制是 256^2-1即65535，作为边界取值的话，拿不到…