对于Unity运行场景中,有许多可以标记场景状况的参数。这篇文章主要探讨这些参数的意义,其中如果有错误欢迎指正。
Game Stats
点击游戏Tab
下的Stats
可以展开如下界面,可以方便我们查看游戏运行状态。
FPS & Time per frame
FPS是通常说的帧率。每帧用时指的是渲染一帧需要消耗的用时,这个值只包含每帧更新游戏视图的时间,不受其他在编辑器中功能的影响,例如Profiler。FPS是这个数字的倒数。值得注意的是,这个值会比我们通常说的帧率要高,因为我们是直接计算两帧之间的时间差的。我猜想手机打包之后两个值的差会变小,但也不会绝对一样。
Batches & DrawCall
这个是绘制图像的重要指标,可以作为衡量场景绘制效率的首要参考。
一个 Draw Call,等于呼叫一次 DrawIndexedPrimitive (DX) or glDrawElements (OGL),等于一个 Batch。
NVIDIA 在GDC上曾提出 25k batch/sec的渲染量会使1GHz的CPU达到100%的使用率,因此使用公式
25K?n(GHZ)?Percentage/Framerate=Batch/Frame
可以推算出某些CPU可以抗多少Batch。例如红米手机CPU为1.5GHz,假设分出20%资源供渲染,希望游戏跑到30帧。那么能抗多少DrawCall? 25k * 1.5 * 0.2 / 30 = 250。因此从这方面也能看出,如果CPU不能分出更多的资源供渲染计算,能抗的DrawCall就会变少。
在Stats面板中看到的Batches是渲染的总Batch这个值等于同于DrawCall。但Unity中可以获取到未批次处理之前的DrawCall。因此需要注意不要混淆概念。
Saved By Batching
这个值是由于Batch减少的DrawCall,可以间接的看到场景优化的效果。这个值由两部分组成:Static Batching
和Dynamic Batching
。这个由Unity内建自动合并虽然优点多多,但也不是没有缺陷。静态合并会引发内存和存储的额外开销,动态合并会增加CPU的负担。 这部分内容参考Unity官方文档
总体上讲所以希望批次渲染的元素要有相同的材质。通常两个材质如果只有贴图不同,可以将贴图合并到一张大图中,这就是所谓的和图。另外在使用ShadowCaster
时,只要材质相同,即使贴图不同也可以合并渲染。
Dynamic Batches
动态合并在满足以下条件时是自动完成的:
- 模型总顶点数小于900。
- 不包含镜像transform改变。不改变Scale。
- 如果使用动态lightmap需要指定正确。
- 不使用多Pass的Shader.
由于需要在合并时通过CPU计算转为世界坐标,这项技术只在CPU消耗比DrawCall消耗“便宜”时才值得。这个衡量标准会根据平台产生差异,例如苹果平台上DrawCall的消耗便宜,就不应该使用这项技术。这个功能可以在Editor
->Project Setting
->Player
中进行设置打开与关闭。
Static Batches
场景中不能移动的物件可以使用静态合并,它不受顶点数的限制,可以大幅减少DrawCall。但为了将元素合并到一个大模型中,这项技术需要额外的内存。主要的内存消耗在于共享多边形会在内存中重复创建。因此有时候需要牺牲渲染效率来避免静态合并,来保证内存够小。例如在茂密的树林中使用这项技术会导致大量的内存消耗。
Tris & Verts
摄像机下的所有三角形和顶点这个在低端硬件上也是主要瓶颈。
脚本获取值
其他数据暂时先不关注了,有必要以后可以再单写一篇。在编辑模式下这些数据是可以通过脚本获取到的,不过打出包来不太成。简单写了一下,效果如下:
其中所有的立方体使用静态合并,面片使用动态合并。场景UI一共17个Batch。动态批次1个,静态批次2个(不知拆分规则),批次渲染一共20。每一个动态物体1个DrawCall,共20个,4个动态物体1个DrawCall,17个UI产生的DrawCall,共38个。
相关代码如下:
using UnityEngine;
using System.Collections;
using UnityEditor;
public class testDC : MonoBehaviour
{
#region Unity Messages
void OnGUI()
{
GUILayout.TextField("Total DrawCall: " + UnityStats.drawCalls);
GUILayout.TextField("Batch: " + UnityStats.batches);
GUILayout.TextField("Static Batch DC: " + UnityStats.staticBatchedDrawCalls);
GUILayout.TextField("Static Batch: " + UnityStats.staticBatches);
GUILayout.TextField("DynamicBatch DC: " + UnityStats.dynamicBatchedDrawCalls);
GUILayout.TextField("DynamicBatch: " + UnityStats.dynamicBatches);
GUILayout.TextField("Tri: " + UnityStats.triangles);
GUILayout.TextField("Ver: " + UnityStats.vertices);
}
#endregion
}