UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - 渲染
type: channel
link: https://blog.uwa4d.com/tag/渲染/
items: Unity的PBR扩展
items: Unity引擎模块分析—注重效率的你不妨这么做！
items: 浅谈PBR在手游开发中的适用性
items: 如何设计渲染等级？
items: 如何制作RTS游戏的寻路系统？
items: 如何把握卡通渲染的制作流程？
items: 如何渲染低分辨率的DepthTexture？
items: 如何更深入地掌握研发项目的物理性能？
items: Journey中的沙丘渲染及其Shader实现
items: 关于Unity UI的动静图集分离，你需要了解这些！

Unity的PBR扩展
type: item
date: 2018-12-26T03:39:00+02:00
description: 基于物理的渲染(PBR, Physically Based Rendering)采用了物理真实的光照模型，符合自然世界的直观认知规律，近年来比较流行。 PBR可理解为是一套渲染标准，标准化有利于简化美术流程，但是只使用标准PBR达不到具体项目的渲染需求，因为游戏风格差异化大多来自对渲染的自定义，比如卡通化PBR渲染： 异度之刃2的游戏截图 上图为NS主机游戏异度之刃2的游戏截图，角色脸部和头发都是比较卡通的，其它部分的金属质感盔甲和场景也都是写实风格的。 异度之刃2在非真实建模的前提下，使用真实渲染和非真实渲染结合，配合后期调色，形成了游戏特有的卡渲风格。游戏中角色脸部和头发渲染这种具有PBR属性，但又风格化的渲染就属于扩展PBR。 一、标准PBS PBR的核心是PBS（Physically Based Shading）着色模型，具体实现由各大引擎自己负责，Unity的PBS实现封装为Standard，Unreal 4（下称UE4）中实现封装为Default Lit。本文的扩展是在Unity的标准PBS的基础上去修改和扩展，这里先剖析Unity的标准PBS的代码实现。 1.1 BRDF BRDF（双向反射分布函数）光照模型是PBS的重要组成部分，用于描述光在物体表面的反射情况。该模型基于微表面理论，认为光在物体表面反射的光量是物体表面的所有微小表面漫反射和镜面反射光量的总和，符合能量守恒： 1） 反射的光总量不大于入射的光总量，且漫反射和镜面反射是互斥关系； 2） 粗糙的表面反射的光线分散且暗，光滑的表面反射集中且亮。 Unity的BRDF的内部实现文件为UnityStandardBRDF.cginc，主要实现函数为BRDF?_Unity_PBS。Unity的BRDF实现按平台分为3个档次，这里讨论的是针对Console/PC平台，光照模型更加精确的第1档实现BRDF1_Unity_PBS。 BRDF的漫反射部分为Disney漫反射模型，该计算模型基于表面粗糙度，主要实现代码为： half nlPow5 = Pow5 (1-nl); half nvPow5 = Pow5 (1-nv); half Fd90 = 0.5 + 2 * lh * lh * roughness; half disneyDiffuse = (1 + (Fd90-1) * nlPow5) * (1 + (Fd90-1) * nvPow5); half diffuseTerm = disneyDiffuse * nl; 代码中diffuseTerm 为计算得到的漫反射部分。 Disney漫反射模型与不考虑表面粗糙度的Lambert漫反射模型实际效果区别不大，所以在Unity的第2,3档中diffuse计算用的是更简单的Lambert模型。 BRDF的镜面反射部分基于Torrance-Sparrow微表面模型，公式类似为： 主要实现代码为： #if UNITY_BRDF_GGX half V = SmithJointGGXVisibilityTerm (nl, nv, roughness); half D = GGXTerm (nh, roughness); #else half V = SmithBeckmannVisibilityTerm (nl, nv, roughness); half D = NDFBlinnPhongNormalizedTerm (nh, RoughnessToSpecPower (roughness)); #endif F = FresnelTerm (specColor, lh); half specularTerm = (V * D * F) * (UNITY_PI/4); 代码中SpecularTerm 为计算得到的镜面反射部分，实现上基本遵守了Torrance-Sparrow的公式。 其中，法线分布D和几何衰减G按是否采用GGX计算模型会有些不同。这里附一张不同粗糙度的法线分布函数（NDF）曲线示意图： 上图中，X轴为Half半角向量和表面Normal的夹角弧度，Y轴为NDF返回值，可看出Smoothness越高的函数曲线越陡峭，可解释“粗糙的表面反射的光线分散且暗，光滑的表面反射集中且亮”能量守恒。 公式中的Frensnel部分的代码实现为： inline half3 FresnelTerm (half3 F0, half cosA) { half t = Pow5 (1 - cosA); // ala Schlick interpoliation return F0 + (1-F0) * t; } F = FresnelTerm (specColor, lh) FresnelTerm 的函数曲线符合之前《理论基础》文章…

Unity引擎模块分析—注重效率的你不妨这么做！
type: item
date: 2018-09-28T16:21:00+03:00
description: UWA GOT是UWA推出的本地性能优化工具，其Online功能限时免费中，并受到了大量开发者的试用和积极反馈。其中，它的总体性能分析模式主要便于研发团队直观地定位、验证和解决逻辑代码中的效率瓶颈。 然而我们知道，引擎模块的性能同样至关重要，仅仅逻辑代码的检测还无法实现系统、完整地定位瓶颈的目的。所以今天，我们在该工具中推出Unity引擎模块的检测。您只需要拥有一个UWA GOT，在本地真机上测试后即可把数据同步到官网，这些详细的数据就能立马呈现。 详细的引擎模块参数 目前，UWA GOT Online报告支持渲染、UI、粒子、动画、加载和物理这六大主流引擎模块的重要参数检测。如下图，在渲染模块页面中，我们可以查看不透明、半透明、视域裁剪CPU和相机后处理等CPU耗时的走势以及某一帧上的耗时。 我们也可以缩放某段测试区域，结合运行截图更直观地定位某些峰值处的表现。 对于引擎模块的重要参数，我们提供了UWA推荐值和相关的优化建议，便于研发团队进行有的放矢的排查和优化。 精准的逻辑代码堆栈 堆栈信息是我们定位性能瓶颈的鹰眼，这次版本的更新不仅丰富了引擎模块的重要参数检测，在逻辑代码中也可以查看更细致的引擎函数堆栈信息，并且通过总体、指定场景和指定帧来定位具体的调用详情。 特别的，在堆栈信息列表中，我们也提供了历史数据对比功能，针对于研发团队定制的性能或功能回归测试，我们可以直接在报告中查看指定重要参数的变化趋势，便于开发团队可以在第一时间验证测试结果。 这次的新功能小编就安利到这里啦！目前，该功能也在限免使用中，研发团队只需要拥有一个UWA GOT，就可以在总体性能分析模式中体验到该功能！还不快打开你的黑科技试一试呀^_^！ 关于UWA GOT Online UWA GOT 是UWA推出的本地性能测评工具，它方便研发团队在本地真机测试，并能在编辑器中搭建本地服务器查看性能数据。现在，在UWA GOT现有的本地测评模式上，我们增加了线上同步和分析功能，研发团队可以将本地测评的数据快速同步到UWA官网，生成在线测评报告，提供更高效的性能分析数据及有针对性的优化建议。同时，贴心的版本对比功能，方便研发团队轻松监测每次测试中的重要性能参数变化趋势，从质量管控上为项目的研发保驾护航。

浅谈PBR在手游开发中的适用性
type: item
date: 2018-05-03T04:33:00+03:00
description: 本期聚集话题：PBR在手游开发中的适用性、如何设计渲染等级（进阶版）、如何判断硬件支持GPU Instancing、25个你需要规避的DrawCall增长的问题... 这是第109篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间15分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群：793972859（仅限技术交流） 渲染 Q1：我们是MMO游戏，现在想给主角（包括其它玩家）使用PBR材质（Untiy自带的Standard），其它角色和场景不使用。不知这种情况下性能是否能抗住，同时我也想了解下目前手游中对于PBR材质的使用情况。 UWA：目前手游中使用PBR材质的项目明显增多，特别是MMO、RPG等项目中，主要的角色、NPC和大Boss等都开始往PBR方面走了。 如果PBR仅是在以上情况下使用时，Unity引擎自带的PBR是没有太大性能问题的，因为一般角色占据的屏幕面积都会比较小，而过剧情时，虽然屏幕面积占据较大，但时间一般都很短，所以给总体性能造成的压力不大。 但是UWA暂时还不建议大家在地形等常常在屏幕中占据较大面积区域的物体上使用PBR（尤其是中低端设备），因为它确实会造成较高的GPU压力，我们在UWA Day 2018上也对此进行了定量分析（类似下图），这点需要研发团队在使用时注意。但是，一切应该以自身项目测试为主，具体查看项目在自己设定的低配机器上到底性能如何。 最后，在使用Standard Shader时，除了关注性能外，还要关注下它对于内存的影响，可以参考这篇文章：【求知探新】Unity中ShaderLab内存优化 该回答由UWA提供，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5ae2f40132493548fbd32bbc 渲染 Q2：UWA DAY 2018大会中说有25种造成DrawCall增长的原因，我想知道是哪25种呢？ 导致批处理失败的原因如下： 1、Additional Vertex Streams — 对象使用MeshRenderer.additionalVertexStreams设定了额外的顶点信息流。 2、Deferred Objects on Different Lighting Layers — 该物件位于另一不同的光照层中。 3、Deferred Objects Split by Shadow Distance — 两个物体中有一个在阴影距离范围内而另一个不是。 4、Different Combined Meshes — 该对象属于另一个已合并的静态网格。 5、Different Custom Properties — 该对象设定了不同的MaterialProperyBlock。 6、Different Lights — 该物件受不同的前向光照（Forward Light）影响。 7、Different Materials — 该对象使用不同的材质。 8、Different Reflection Probes — 该对象受不同的反射探头（Reflection Probe）影响。 9、Different Shadow Caster Hash — 该对象使用其他的阴影投射着色器，或是设定了不同的着色器参数/关键词，而这些参数/关键词会影响阴影投射Pass的输出。 10、Different Shadow Receiving Settings — 该对象设定了不同的“Receive Shadows”参数，或是一些对象在阴影距离内，而另一些在距离之外。 11、Different Static Batching Flags — 该对象使用不同的静态批处理设定。 12、Dynamic Batching Disabled to Avoid Z-Fighting — Player Settings中关闭了动态批处理，或在当前环境中为避免深度冲突而被临时关闭。 13、Instancing Different Geometries — 使用GPU Instancing渲染不同的网格或子网格。 14、Lightmapped Objects — 对象使用了不同的光照贴图，或在相同的光照贴图中有不同的光照贴图UV转换关系。 15、Lightprobe Affected Objects — 对象受其他光照探头（Light Probe）影响。 16、Mixed Sided Mode Shadow Casters — 对象的“Cast Shadows”设定不同。 17、Multipass — 对象使用了带多个Pass的着色器。 18、Multiple Forward Light…

如何设计渲染等级？
type: item
date: 2018-04-27T04:42:00+03:00
description: 本期聚集话题：PBR在手游开发中的适用性、如何设计渲染等级（进阶版）、如何判断硬件支持GPU Instancing、25个你需要规避的DrawCall增长的问题... 这是第108篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间15分钟，认真读完必有收获。 UWA 问答社区：answer.uwa4d.com UWA QQ群：793972859（仅限技术交流） 渲染 Q1：现思考如何设计项目中的渲染等级，求有经验的大佬指个方向，例如ShaderLOD，还有其他什么思路吗？谢谢！ 整理了一下我们游戏中效果分级的内容，供参考： 感谢贾伟昊@UWA问答社区提供了回答，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5acc208b425802635474fc7d 渲染 Q2：我用2017.2.0渲染一张地图，为什么在小米4上Camera.Render会有很高的耗时？一个空场景，为什么Camera.Render耗时这么高？ UWA：我们做了一个简单测试来研究一下这个问题，即在场景中只渲染一个Cube。 机型： （1） 华为6Plus （2） 小米4 Profiler截图如下，蓝色框：华为6Plus 红色框：小米4 由上图可知，小米4的Camera.Render耗时不稳定，有时候会出现10+ms的峰值。 通过查看Unity Profiler以及和其他设备进行对比，发现了以下两点是造成小米4上耗时不稳的原因： 1、Culling不稳 下图为小米4和华为6Plus设备上，Culling操作的耗时比较。蓝框为华为6Plus设备，红框为小米4设备。通过Timeline可以看到是场景SceneNode的计算导致。 2、Drawing不稳 渲染耗时也同样不稳定，如下图所示：通过Timeline发现，小米4设备上，主线程的渲染进程会经常等待子线程完成后再进行后续操作，而同样的App，在华为6Plus上则不会如此表现，如下图所示。 小米4： 华为6Plus： 因此，对于上述测试做个总结： （1） Culling中的SceneNode计算操作在小米4设备上经常伴随更为耗时的CPU开销； （2） 小米4上更容易表现出主线程渲染等待子线程的情况。 以上两点是题主问题的主要原因，但至于更深层次的解释，这个恐怕要联系手机研发厂商甚至底层芯片硬件厂商了。但需要说明的是，这仅是一个简单测试例子的表现情况，复杂场景并不一定同样适合。但测试和分析方法都是不变的，题主后续如有需求，可自行测试寻找答案即可。 欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5ada00363dba2a108c7e3236 渲染 Q3：我们用的Unity 5.5场景带有2级LOD，我们使用Lightmap渲染场景，结果次级的LOD模型渲染出来的阴影面是纯黑的，这个该怎么办呢？烦请大神指点！ Untiy官方在5.5版本里其实是不支持LOD的Lightmap的，即便是到了2017.4版本里，官方文档也是让你去使用Light Probes：https://docs.unity3d.com/Manual/LODForBakedGI.html 当然它也说到： “When you use the Progressive Lightmapper, there is no need to place Light Probes around the LOD Group to generate baked indirect lighting. However, to make Realtime GI affect the Renderers in the LOD Group, you must include the Light Probes.” 我们也是在用Unity 5.5版本，没有试过Progressive Lightmapper，不知道效果如何。所以第一个解决方案是升级到Unity 5.6或者Unity 2017尝试下Progressive Lightmapper。 如果想在Unity 5.5的下面做，我们是使用手动拷贝烘焙后的scale和offset的方式来实现，就是在运行时将原始模型的光照题图信息完整地拷贝给LOD低层级的模型。但是这有一个非常强的限制：要保证两个模型的UV2是完全可以对应上的，否则UV2可能会出现一些错乱。使用Simpylgon这样的中间件可以做到尽量保持UV2不变。 这样做有两个问题： 如果是减少了很多面的模型，比如删除掉了一个组件，结果组件露出来的面因为之前是被遮挡的，会是黑色的。不过大部分情况下减面很多的LOD模型也会距离很远，这…

如何制作RTS游戏的寻路系统？
type: item
date: 2018-04-13T04:44:00+03:00
description: 本期聚集话题：RTS游戏的寻路系统、AssetBundle打包后md5不同、UGUI中3D血条优化问题、如何快速改变场景里一部分物件的外观效果... 这是第107篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间15分钟，认真读完必有收获。文末，我们的互动话题是：能耗发热怎么办？期待你的灼见！ UWA 问答社区：answer.uwa4d.com UWA QQ群：793972859（仅限技术交流） 本文封面图来源：RTS手游《战地指挥官》 http://zdzhg.53mayi.com 寻路 Q1：我们在做一个RTS游戏，开始用的是Unity自带的NavMesh的寻路，但发现这个并不适合RTS多人寻路，因为总会出现阻挡和闪跳的问题。看Asset Store上的A* path插件评论说在碰撞上有问题，不知道大家是否能提供比较成熟的解决方案？ 我们上一个项目是RTS项目，刚开始寻路问题解决方案过程中遇到过和你相似的疑惑，修改探索和调教了很长时间，分享几点供题主参考下。 先上结论：我们采用了两层结构 A Start Pathfinding Project Pro + Unity NavMesh。 1）主体寻路方案使用 A Start Pathfinding Project Pro 这个插件中传统的网格形式，并进行了深度修改扩展，主要是满足寻路过程的通路性需要考虑到单位半径大小，这样寻路精度高； 2）使用Unity NavMesh系统作为寻路过程中的碰撞系统，因为你说的很对，这个寻路插件的碰撞有问题，稍后解释。 以上两部分组成“寻路算法+精确碰撞”。接下来说下以上方案的原因和细节。 1、NavMesh寻路速度快但不够精确。RTS还是适合使用传统的四方形NavGrid格子寻路，而且现有的任何寻路算法默认都是不支持考虑寻路单位半径大小对寻路过程的影响，但我们策划绝不允许1米宽的缝隙被一个两米宽的胖子挤过去，如果使用Navmesh并且动态生成阻挡会出现寻路路径是有了，可是由于碰撞问题大的单位会卡在缝隙这里来回“发抖”的情况；这个只能自己动手修改，所以我们买了该插件然后自己从里到外修改，具体修改算法原理和修改后的示意图，你可以参考这里：http://www.cnblogs.com/yaukey/p/rts_unit_traverse_size_based_path_finding.html。 修改完后，每次寻路会将单位的直径大小当做寻路参数之一传入进行寻路。 使用这个插件开启两个线程左右来寻路是我后来调教出的、一个比较理想的结果。然后是地图中各种单位会出生和死亡，当单位站定不动，需要生成阻挡；移动了需要移除阻挡恢复此处的通路性，通过再修改下插件中的DynamicObscule这个组件（原生功能太简单）来实现；我们具体是每个单位都有一个对应的大小的CapsuleCollider空对象挂上这个脚本，单位站定将该物体放置到单位的位置并激活它，单位移动隐藏该空物体即可，这个脚本会引起地图通路性的更新，这个更新是多线程的，这一点是要注意的，通过回调事件来做响应的事情，切记不要在同一帧或者下一帧去做，因为即时性不能保证。这样就能让整个地图一直根据单位来更新通路性。 2、寻路的通路性问题解决了，现在来解决碰撞问题。这个插件自带了碰撞算法，使用的rvo算法，但是据我当初各种调教实验，它的碰撞都达不到我们的要求，单位多了拥挤的时候总是会有些单位站立后变得重叠了，最不能接受的是两个单位完全重叠。在这里我花了相当多的时间都不能修改出的满意的效果。后来想起来recastnavigation作者亲口说过虽然Unity的NavMesh基于此，但是Detour系统经过深度的改写，Detour包含了巡航和碰撞，而实际使用也发现NavMeshAgent之间的碰撞是很精确的，于是我想了个取巧的办法，给地表再铺一层跟AStar插件的寻路面积一样大的NavMesh，但是没有任何的阻挡（理解为一片纯蓝色），同时给寻路单位添加一个NavMeshAgent，然而这个东西只用它的碰撞，而不使用寻路（没有阻挡，任何寻路都是两点直线，可以考虑几乎无开销），这样最后实际的碰撞效果才算达到我们满意的效果。 以上就是我所说的两层含义，我再说下坑和问题。 1）当初开发Unity版本是Unity 5.3.7-5.3.8，插件版本5.x，寻路插件中底层会有Physics.CheckCapsule调用，但是多线程大量调用，会导致底层PhysX物理引擎崩溃，游戏闪退，不必现但是大量的话很容易一下就挂，插件官方论坛也有这个Bug讨论，后来我将此换成了两个 Physics.CheckSphere 调用，目前2017版本没有测试过； 2）我在1中使用的方法，在UWA性能评测中…

如何把握卡通渲染的制作流程？
type: item
date: 2018-04-10T04:56:00+03:00
description: 本期聚集话题：卡通渲染的制作流程、没用物理模块，为什么还会有物理引擎的耗时？SpriteAtlas的late bind机制、ASTC在安卓平台使用的可行性、UI 性能分析... 这是第106篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间15分钟，认真读完必有收获。文末，我们的互动话题是：资源的同步和异步加载，哪个更受你的青睐，我们期待你的灼见！ UWA 问答社区：answer.uwa4d.com UWA QQ群：793972859（仅限技术交流） 本文封面图来源：ACT手游《崩坏3》 https://www.bh3.com/picture.html 制作 Q1：我最近在Unity中制作角色的卡通渲染效果，目前的工作流程是这样的：1）程序在Unity中写Shader调效果；2）美术在3dmax修改模型顶点色和法线等资源，修改完导出给程序；3）程序将资源导入Unity中验证效果。目前需要频繁地修改资源、导出导入资源，效率比较低下。 所以我有以下两个问题： 1、如何在3ds max中写着色器，美术修改模型后能及时看到效果？ 2、成熟的制作流程是什么样的？ A1：这个不难的，让渲染程序员简单看一下Maya或者Max的文档，几个小时基本都是可以搞定的，Max或者Maya都有例子和文档，比如Max的话就是用DirectX Shader Material，不用把这个想得很难，好好看文档。 我觉得本质上主要是想要所见即所得，所有的工作也都是为了这个目的。卡通渲染对美术资源的修改大多需要定制化，例如靠刷顶点色控制描边，靠改顶点法线去改善光照，所以如果把Shader做到Max里可以大大提高美术的制作流程，而不是总是导入导出。通常的流水线是：维护一个和引擎预览效果一致的Max（或Maya）Shader材质，再加一个自定义的法线编辑工具（如果美术觉得内置的不够用，比如Max的法线编辑比较困难），这样在修改美术资源保证效果一致性就好了。 感谢乐乐@UWA问答社区提供了回答 题主补充：对于第一个问题，读书哥提供了一个方法：Max里可以用HLSL写，有DX9/11的Sample，但是问题挺多的，Driver建议用Nitrous Direct 3D 9，记得关掉Gamma/LUT和SSAO。 附上参考文档链接：http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-SDK-Programmer-Guide/index.html?url=files/GUID-0C7A600E-7954-42B0-86EE-586A379A2CAD.htm,topicNumber=d30e34269 欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5ac0dbc1910222635366dc85 UI Q2：我们打开UI界面Profiler峰值显示 Canvas.SendWillRenderCanvases消耗了50%CPU开销，Canvas.SendWillRenderCanvases 消耗80ms，Graphic.Rebuild 消耗了72ms，请问有什么办法可以优化呢？ UWA：这是某个/某些大量的UI界面元素的重建开销，建议如下： （1）先通过“动静分离”原则检测是否有不必要的静态UI网格参与了重建； （2）UI界面是否过于复杂，UI层级或者网格量是否过大； （3）在UWA性能简报中查看对应的解决方案和相关视频，磨刀不误砍材工。下图中可以看到这些参数在每次测评中的走势，耗时下降的很快：） 该问题由UWA提供，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5ac49b99910222635366dca9 物理 Q3：如下图，我们物理模块中没有用到任何碰撞对和Rigidbody，为什么还会有物理模块的耗时呢？ UWA：题主的Unity版本是多少的？如果是Unity 5.4版本以后，那确实不太正常，因为Unity引擎在5.4后对物理系统做了调整。 如果是Unity 5.4之前版本，那么就是比较正常了，因为无论你是否使用，物理模块每帧都在运转，你可以理解为是空转。对此，题主需要查看报告中“重要参数解析->引擎性能参数”中的“Physics.Processing”或“Physics.Simulate”一页，里面有这两个函数的调用次数。很多时候，物理模块即便没怎么用，但由于是每20ms运行一次（默认情况下），也会在同一帧中运行很多次，如下图所示。所以，物理模块有个特点，就是当你项目卡的时候，它会让你的项目更卡：）对于这种情况，题主只需要去优化其他模块，当其他模块的耗时下来后，你会发现物理模块…

如何渲染低分辨率的DepthTexture？
type: item
date: 2018-04-02T13:12:00+03:00
description: 本期聚集话题：材质（贴图）之间的性能影响、粒子系统不断修改发射点的性能最优解、如何渲染一个低分辨率的DepthTexture、Unity中物体实时光照的性能开销... 这是第105篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间15分钟，认真读完必有收获。文末，我们的互动话题是：.net 4.6是否值得尝鲜？ UWA 问答社区：answer.uwa4d.com UWA QQ群：793972859（仅限技术交流） 制作 Q1：请教一个问题，我们项目中有一种粒子系统需要不断地修改发射点，用worldspace模式确实可以达到一定的效果，但是目前需要在一帧里从若干个位置同时发射粒子，用多个相同的Particle System确实可以达到目的，但总觉得有些浪费，容易造成频繁的创建和销毁，如果都缓存的话总数可能就会很大了，不清楚有没有可能用一个Particle System来实现这个效果？ 可以参考这个文档: https://docs.unity3d.com/ScriptReference/ParticleSystem.Emit.html 通过调用ParticleSystem的Emit方法来发射粒子，可以在一帧里用不同的EmitParams进行多次调用Emit。这样的话，粒子系统本身就不用移动了，只是每次Emit的位置参数不同。 感谢zZ@UWA社区提供了回答，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5abde6cd425802635474fbb1 资源管理 Q2：情景1：一张512x256的纹理。情景2：两张256x256的纹理。请问以上哪个情景消耗会更大呢？ 进一步再说，一个同样的角色，情景1：一个材质球，一张512x256的纹理，情景2：两个材质球，各256x256的纹理，这种情况下又是哪个情景消耗更大呢？判断依据和原理是什么呢？ UWA：就内存方面，设置相同的情况下，二者应该是一致的（某些需要长宽相等的压缩格式除外）。 在CPU开销方面，那么二者基本上也可能是差异很小的。如果是一个材质，一张和两张的区别在于采样次数。一张纹理会减少一次纹理的绑定开销，理论上减小的耗时开销是在ns级别的，所以在绝大多数实际情况下CPU端的差异都可以忽略不计；如果是两个材质，影响的因素就会多了，可能会造成更多的Draw Call、更多的RenderState切换等等，这就是为什么要采用Atlas Packing的优化原因。 至于GPU上的开销，多一张纹理的Shader采样肯定要多一些计算，所以Shader Instruction和Cycles肯定也会更多一些。但是否真的是会带来更大的实际开销呢？不一定，因为GPU压力不光是要看一个Shader的Instruction，同时还要看Runtime到底有多少像素是通过这个Shader来渲染的，如果本身占比很小，那么多一次采样和少一次采样，在实际情况下没啥区别。 该回答由UWA提供，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5abdca59910222635366dc77 渲染 Q3：我想渲染一个低分辨率的DepthTexture，有什么比较方便的做法吗？ 一种方式是自己创建一个低分辨率的RenderTexture，然后通过Shader Replacement来渲染一个DepthTexture（Shader可以参考Unity的ShadowCaster的实现）。 还有一种是通过_LastCameraDepthTexture来访问其他的低分辨率相机（如果有的话）渲染出来的DepthTexture。 感谢zZ@UWA社区提供了回答，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5abde736910222635366dc78 渲染 Q4：我想了解下Unity中物体接受灯光、产生阴影、接受阴影的性能开销情况。之所以这么问，是想看看Unity中的以上三种的性能开销。另外，在移动端是否有开启以上三种，或者部分的可能性，谢谢。 UWA：题主的“接受灯光”是指接受Real time光照吗？如果是的话，那么这种性能开销是没法预估的，因为它跟你的渲染场景复杂程度、接受光照物体的多少等都有很大关系，并不能简单理解成“开启就耗时、绝对不可以开启”。建议看看这篇文章：【求知探新】独立游戏《Abi》场景耗时分析 “产生阴影”和“接受阴影”是实时阴影功能的两个选项而已，建议在UWA性能报告中关注Shadows.RenderShadowMap和Shadows.PrepareShadowMap两项，从而来看到你项目的具体性能…

如何更深入地掌握研发项目的物理性能？
type: item
date: 2018-03-26T13:15:00+03:00
description: 本期我们聚集了这几个话题：如何提高Unity物理引擎Physx的性能、如何禁止Unity自动编译脚本、使用Texture2DArray时开启Mipmap效果... 这是第104篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题，建议阅读时间15分钟，认真读完必有收获。文末，我们的互动话题是，Mono和IL2CPP，哪个更受你的青睐，我们期待你的灼见！ UWA 问答社区：answer.uwa4d.com UWA QQ群：793972859（仅限技术交流） 封面图片来自Google 物理 Q1：如何提高Unity物理引擎Physx的性能？我在场景中加入100个具有物理刚体的小人，并充分碰撞，发现低端机的帧率只能跑到10帧以下。 UWA：如果需要充分进行物理计算，这些拥挤在一起的小人很可能会造成大量的物理碰撞，进而造成很高的物理耗时。 在优化之前，题主需要先了解一些基础物理数值推荐，并不是所有设备都能流畅跑起100个自由制作的蒙皮模型的。所以，建议先看这篇文章：https://blog.uwa4d.com/archives/Simple_PA_Physics.html 另外，题主还需要看一下真机上的具体耗时瓶颈是否真正耗时在物理上，100个角色，如果Mesh量很大，渲染耗时也是不可忽视的，所以建议通过Unity Profiler来先确定一下真机上性能瓶颈。 最后，是否每个小人都需要精确的物理计算，是否可以通过一些射线求交、范围判断等性价比高的判断方法来代替纯物理碰撞？这需要题主从设计的角度上来进行权衡。 你并没有什么办法直接调用PhysX的API，所以所谓优化物理引擎的性能，倒不如说优化相关组件的性能。首先优先使用CharacterController而非RigidBody。然后尽量避免使用MeshCollider，用BoxCollider、SphereCollider和CapsuleCollider代替，如果不可避免，那么钩上Convex。当然，最好的优化就是不要用物理碰撞。射线能解决很多问题，但是射线也不是免费的，它的消耗跟场景里的面数正相关，当然设置射线的maxDistance和LayerMask能节省掉不必要的消耗。最好就是用简单的物理模型来描述问题，自己写代码实现。 感谢凯奥斯提供了回答 欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5ab47292d35eb22c10a0a403 编辑器 Q2：有什么方法可以禁止Unity自动编译脚本呢？ UWA：可以把Preferences > General > Auto Refresh的勾去掉，不过如果这样，如果资源在外部被修改，也不会自动重新导入了，会有些影响。 另外，也可以试试这两个函数EditorApplication.LockReloadAssemblies/ UnlockReloadAssemblies，参考文档：https://docs.unity3d.com/ScriptReference/EditorApplication.LockReloadAssemblies.html 该问题由UWA提供，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5ab8a76dd35eb22c10a0a41f 渲染 Q3：我使用Texture2DArray的时候发现没有Mipmap效果，想问下怎么让Mipmap生效？原始的纹理都是开启Mipmap的。 UWA：在创建Texture2DArray时需要注意倒数第二个参数，设为true就表示开启Mipmap，参考文档： https://docs.unity3d.com/ScriptReference/Texture2DArray-ctor.html 该回答由UWA提供，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5ab7afd60b827e2c0bfdd18f 制作 Q4：现在有一张外部生成的Texture可以作为mainTex渲染，但希望获取它的内容保存下来，但是GetPixels是Texture2D的函数，所以想问问这样的Texture的内容该如何获取？ UWA：可以先通过Graphics.Blit把内容画到Render Texture里面，然后通过ReadPixels从RenderTexture生成一张Texture2D，假设sourceTex是原始的Texture，tex2D是最终生成的Texture2D，则代码如下： RenderTexture renderTexture = new RenderTexture(sourceTex.wid…

Journey中的沙丘渲染及其Shader实现
type: item
date: 2018-03-06T11:25:00+02:00
description: 在写这篇文章之前，我先给大家展示下，下图是Journey里面的沙丘渲染是很久之前一直想做的，但总是没时间。最近因为项目中在做一个沙丘的场景，所以趁这个机会来做一下。 在这里事先声明，在场景再现中所用到的技术基本上是在尊重Journey原作的精神下进行的个人创作。由于素材，参数以及个人能力等原因，要完全重现Journey里面的场景十分困难，也没有意义。另外在制作时不会考虑开销，一切以效果为重。本作仅希望通过场景复原过程分享与收获一些风格化渲染的经验。 场景最终效果： 官方参考图，是游戏里的实景： 图片来源：Sand Rendering in Journey 这是GDC的一个讲座，现在已经可以免费观看了。讲座用的PPT下载链接：advances.realtimerendering.com 忍不住多方几张官方的插图，因为实在是太漂亮了： 沙子上有blingbling的闪光 为了防止分辨率下降，建议大家下载ppt观看。 好的，鉴赏完毕，接下来是正片。 一、建模 Modeling 讲座里说了是用一个高度贴图height map进行建模。 用于建模的height map 基本方法是把图片下载下来之后，在Maya新建一个平面，把面片数调节为50*50： 然后打开Surfaces->Sculpt Geometry Tool。打开小窗后，选择Attribute Maps->Import 点击import，然后在路径导航窗口中选中刚才我们使用的height map。导入后每个点的高度变化可能有些小，所以我做了沿Y轴的缩放，完成后效果如下： 讲座中提到了他们使用B-spline让模型更加平滑。这部分内容主要和建模有关系，这里就不作展开了。 我希望进行渲染的内容为该场景内的一小部分，所以单独为这个镜头建了一个模，如下图： 基本上就是用Maya的Sculpting工具修修改改一点点捏出来的。Journey风格的山丘，特点就是山头很尖，一定要尖，做山头的时候可以改用soft select 来调节vertex。 改完后把模型导入Unity，打上背光： 阳光的颜色为（253，208，179）。背景的日光有些丑，所以替换成Jouney的抱抱山和游戏场景中灰黄色的天空。山是游戏截图（估计真实的游戏也就是一个图片( :3 )），天空是一个外部剔除的球体，大概长这样： 修改过后镜头里的画面： 这里还导入了一个Unity自带的FirstPersonController。这样就可以愉快地在沙丘上跑了。写Shader前的准备工作基本完成。接下来本文就讲座所提及的内容，以倒叙的方式实现（谁叫讲座也是倒过来讲的呢）。 二、基本的明暗 Diffuse 新建一个新的Unlit Shader，建好后加上材质给我们的模型贴上。 首先是一些基本的向量转换的工作，这里贴一下顶点函数： struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal : NORMAL; float4 tangent :TANGENT; }; struct v2f { float2 uv : TEXCOORD0; float3 worldPos : TEXCOORD1; // position of this vertex in world float3 view : TEXCOORD2; // view direction, from this vertex to viewer float3 tangentDir : TEXCOORD3; // tangent direction in world float3 bitangentDir : TEXCOORD4; // bitangent direction in world float3 normal : NORMAL; UNITY_FOG_COORDS(5) float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; // here we don't want the main texture to affect the uv o.worldPos = mul(unity_ObjectToWorld ,v.vertex).xyz; o.view = normalize(WorldSpaceViewDir(v.vertex)); o.normal = normalize( mul( unity_ObjectToWorld , v.normal).xyz ) ; o.tangentDir =…

关于Unity UI的动静图集分离，你需要了解这些！
type: item
date: 2018-03-06T03:39:00+02:00
description: 本期我们聚集了这些话题：UI 图集静态分离、Unity烘焙问题、Unity渲染异常、Animation.RebuildInternalState......(UWA一下，你就知道~） 这是第101篇UWA技术知识分享的推送！（此处应有掌声）随着大家在UWA平台上的发言愈加活跃，我们也源源不断地收到了许多技术大咖的热心回复和真知灼见。 UWA 问答社区：answer.uwa4d.com UWA QQ群：793972859（仅限技术交流） UI 管理 Q1：对于Unity的静态图集和动态图集分离，我有些疑问。我们UI制作方法如下： Prefab (UIHero) Prefab的静态图集 (UIHeroAtlas) Prefab上可能的动态图集 (UIHeroIcon) 如头像 生成的Bundle： Prefab一个bundle,它包含了静态的图片 动态图集一个Bundle 后来，为了能动态合批减少几个DrawCall，可能静态图集上有2-3张图片，在动态图片的上面当一个小边框背景。然后美术想把它放到动态图集，这样图片重叠时，它和动态图集的图也会是一个DrawCall。 我们的问题是：在使用AB的方式加载这个UI-prefab时，会不会加载整个动态的图集（UIHeroIcon）呢？还是说不会加载整个UIHeroIcon，只是把这两个静态图加载，动态UIHeroIcon照样不会加载？这种方式是否会造成热更新UIHeroIcon动态图集后，导致UIHero-prefab无法加载这两个静态图片的情况？那么我该如何取舍？ 1.会不会加载取决于你，Unity只是给出依赖列表，是否加载自行控制。 2.不会加载整个UIHeroIcon。 3.这里差不了几个DrawCall。而前景可能有很多种，美术的方案不一定通用，以后可能会拆回来。我的理解是，是静态图集中有2个Sprite A和B，然后在动态图集中也复制一份A和B。重叠时，如果UI深度不同，不一定可以合并。资源结构为重，不然之后维护会很麻烦。 感谢UWA问答社区 @史云柯 提供了回答 UWA补充：补充下史云柯回答中的第三点，建议评估下DrawCall能节省多少。举个例子，如果是个10人MOBA，那么在团战过程中10个Icon可能是叠在一起的，由于图集穿插就有可能增加到20个DrawCall，对于中低端设备节省20个DrawCall的话，性价比还是可以的。如果最差情况也就10个不到，那么确实性价比不高了。 此问答来自于UWA 问答社区，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5a94dd200b827e2c0bfdd022 渲染 Q2：请问各位Unity5.3烘焙得到的LightingData.asset、Lightmap-0_comp_dir.exr、Lightmap-0_comp_light.exr各有什么作用呢？打包和加载的时候实际上是用了哪一个文件，还是全都需要？ UWA：LightingData.asset的介绍可以看这两个文档： https://docs.unity3d.com/Manual/LightmapSnapshot.html https://answer.uwa4d.com/question/5a4f4367e041ef3c50c9ce64 简单说，这里面存的就是场景中各个受Lightmap影响的物件的相关信息，Editor下这个文件可能会很大；但真机上，在不使用precomputed gi的情况下这部分的数据打包到手机上应该是很小的（毕竟对于一个物体来说，主要的Lightmap信息就是lightmapIndex和lightmapScaleOffset）。 另外，这部分信息是和场景文件绑定的，不能单独管理。所以默认情况下，Lightmap只能随场景一起加载。如果需要动态加载lightmap，可以参考这篇文章：http://www.xuanyusong.com/archives/3807；而后面两个.exr文件就是储存光照信息的纹理，_dir是光的方向信息，_light是光强信息（最简单的模式下只需要这一张）。这些文件是运行时需要的，不过exr是支持HDR的格式，在手机上会默认转成其他格式的，大小与exr是不同的。 该回答由UWA提供，欢迎大家转至社区进行进一步交流： https://answer.uwa4d.com/question/5a9a69720b827e2c0bfdd0a7 动画系统 Q3：Camera.Render里面Animation.RebuildInternalState耗时较多，调用比较频繁，这个主要是哪些情况会调用呢？ UWA：之所以出现这一项，主要可以说明一下两点： （1）题主项目用的是Ani…