技术分享连载(五十三)

技术分享连载(五十三)

本期话题:如何减少Lightmap纹理数量 、UGUI 重绘、Dynamic Batching、UGUI重绘机制...精选了5个性能优化问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。

UWA 问答社区:answer.uwa4d.com
UWA QQ群:793972859


图形渲染

Q1:请问“Dynamic Batching”这个选项开关与否对于性能影响大么?
请输入图片描述

一般情况下,如果可以我们还是建议开启该选项。下图是我们做的一个实验,即在红米2设备上渲染将近100个动态Cube。Profiler面板左侧为开启Dynamic Batching的CPU耗时(不透明渲染耗时0.5ms左右),右侧为关闭Dynamic Batching的CPU耗时(不透明渲染耗时1.5ms左右)。可以看出,两者耗时相差将近1ms。当然,不同项目、不同模型,其耗时差距是有一定不同的。因此,建议研发团队可以根据自身情况关闭和开启该选项来进行测试。

测试用例:
请输入图片描述

关闭Dynamic Batching的CPU耗时:
请输入图片描述

开启Dynamic Batching的CPU耗时:
请输入图片描述


性能优化

Q2:求教一个屏幕后处理的问题。我们期望角色不受屏幕后处理影响,所以目前采用双相机的方案,根据Layer划分,但是这种情况下角色的影子也就没有办法投影到地表上,请问这种需求有什么好的实现方式?

可以尝试根据地表模型的局部细节来动态生成接受阴影的网格(比如Fast Shadow Receiver插件),这样既可以保证地表模型进行屏幕后处理操作,同时也可以生成相关角色的动态阴影。


资源管理

Q3:请教Lightmap相关的优化问题。我现在的场景中有N个GameObject共用一个Prefab,烘培Lightmap时,会生成出N个Lightmap贴图。有没有办法把这些生成的Lightmap合成一张?

如果场景中某些物件在Lightmap纹理中占据的空间较大,但实际上并不需要较高的精度,那么可以选中该物体,并在Lighting面板的Object子面板中将其Scale in lightmap数值调低,从而可以降低其在Lightmap纹理中的空间,甚至减少Lightmap纹理的数量。


性能优化

Q4:我的项目在一帧中进行实例化操作时,会产生大量的GC Alloc,请问这是为什么?我又该如何避免呢?
请输入图片描述

Unity引擎的Instantiate操作本身是会触发少量的堆内存分配,从图中数值可以看出,该堆内存分配过大的主要原因可能有以下两点:

  1. Instantiate在该帧中调用次数过多,从图中可以看到,在一帧中Instantiate实例化操作被调用128次;

  2. Instantiate实例化后,其GameObject身上的代码组件在执行Awake函数和构造函数(.ctor)时也很有可能产生堆内存,从目前的1.3MB堆内存来看,很有可能是这种原因。

对此,建议研发团队在Unity Profiler中直接查看Instantiate的自堆栈信息,即可定位其具体的堆内存出处。


UI

Q5:请问UGUI的重绘是针对于拥有Canvas组件的Canvas物件,还是针对于拥有CanvasRenderer组件的Panel物件?

UGUI中,Canvas组件可以认为是容器,Image,Text等组件(都需要CanvasRenderer组件)可以认为是元素。在Unity5.2版本之前,在网格重建时,会以Canvas为单位,即一个Canvas中所有的元素最终都是合并到一个Mesh中的,而其中可以被合并渲染的元素则被合在同一个SubMesh中。在Unity5.2版本之后由于引入了多线程的网格合并方式,据我们所知,目前并没有官方的原理解释。

今天的分享就到这里。也欢迎热爱进步的你加入UWA的QQ群(793972859),也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。 比起闭门造车,我们更乐意与大家各抒己见,畅所欲言;比起形而上的泛泛而谈,我们更乐意与大家直击痛点,对症下药。