Q1:在查看《六龙争霸测评精讲》时,看到下图中的GC的调用,请问该数值的是取决于明式调用System.GC.Collect()这个方法吗,还是指系统自动GC的频率?
手动触发System.GC.Collect和系统触发GC都属于GC的调用。除iOS平台外,Unity项目的GC调用是由Mono来控制的。其主要有两种方式,一种是系统每隔一段时间调用一次,一种则是当堆内存分配过大过快时被触发。
每次GC调用均会造成一定程度上的卡顿,从而降低项目运行的流畅度。因此UWA测评中专设了GC调用详细检测。
Q2:在报告中我们看到函数uwa-xxx是我们加的自定义代码段采样, 我们发现它们触发了很多GC, 是什么情况呢?
说明这些函数中会经常分配大量的堆内存 。GC是Mono来控制的,当Mono认为累积堆内存较高时,它就会调用GC。同时,哪个函数在分配堆内存时触发了Mono的GC,该GC调用就会被算作是哪个函数调用的。所以如果经常被特定函数来触发GC,那么从概率上来说这个函数或这个代码段分配的堆内存相当高。
Q3:项目中勾选Static Batching和不勾选对效率有多大影响?我们在使用中发现勾选了以后包大小会增大一倍。如果不勾选,和自己在代码中调用StaticBatchingUtility.Combine的效率有多大区别?
1.如果在Editor中进行勾选,则会在项目中生成一个较大的VBO,Runtime时通过该VBO来进行渲染,优点是有效减少了Draw Call,缺点是增大了发布游戏包的体积。
2.如果在Runtime通过脚本来进行Batching,则相当于把拼合的时间由Editor中搬到了Runtime,所以加载时间(一般在场景加载时执行Batching)会稍有增加,但游戏包的体积将相应减少。
Q4:如何在移动设备上,对Bloom和全屏抗锯齿进行优化?Unity标准资源里面自带的效率比较低(已经尝试过Bloom(Optimized))。
建议使用Asset Store上适合移动端的Bloom Shader插件,比如FxPro: Bloom&DOF和BloomPro等。
对于AA,目前在移动设备上并没有特别优化的方法,仅能建议在低端设备上关闭AA功能,而在高端设备上可尝试开启较低倍数(2x)的MSAA。
Q5:如图,我们在UI打开或者移动到某处的时候经常会观测到CPU上的冲激,经过进一步观察发现是因为Instantiate产生了大量的GC。想请问下Instantiate是否应该产生GC呢?我们能否通过资源制作上的调整来避免这样的GC呢?如下图(图略),因为一次性产生若干MB的GC在直观感受上还是很可观的。
准确的说这些 GC Alloc 并不是由Instantiate 直接引起的,而是因为被实例化出来的组件会进行 OnEnable 操作,而在 OnEnable 操作中产生了 GC,比如以上图中的函数为例:
上图中的 Text.OnEnable 是在实例化一个 UI 界面时,UI 中的文本(即 Text 组件)进行了 OnEnable 操作,其中主要是初始化文本网格的信息(每个文字所在的网格顶点,UV,顶点色等等属性),而这些信息都是储存在数组中(即堆内存中),所以文本越多,堆内存开销越大。但这是不可避免的,只能尽量减少出现次数。
因此,我们不建议通过 Instantiate/Destroy 来处理切换频繁的 UI 界面,而是通过 SetActive(true/false),甚至是直接移动 UI 的方式,以避免反复地造成堆内存开销。
Q6: 关于场景中玩家和NPC名字的DrawCall的问题。我们项目中是使用TextMesh挂到场景单位上,但是这样每个名字就占了一个DrawCall,请问有没有好的办法优化呢?
游戏中的HUD的做法一般有两种,一种是如上的做法,另一种则是通过NGUI/UGUI来制作HUD。第二种的实现方法大致如下:
(1)计算屏幕中角色在屏幕中的位置;
(2)根据屏幕中的位置来计算各自HUD的位置,并根据HUD的数量分别放置在一个或几个Panel/Canvas下。
第二种方法的优势是尽可能用少的Draw Call数来渲染角色的HUD。开发团队可以就该方法来进行尝试。
Q7: 我们能通过Batching来进行效能方面的优化吗?透过粒子发射出来的半透明模型片是无法Saved by Batching ,如果粒子可以使用Dynamic Batching的话,想请教具体的使用规则与方法。
根据Unity 官方的信息,目前粒子系统已经不再进行 Draw Call 的拼合,因为在新版本5.3 中已通过多线程进行更新,暂时无法支持拼合,但性能已经得到提升。
开发团队可以参考:http://forum.unity3d.com/threads/particle-batching.382835/