Stats窗口 ##
Stats窗口,全程叫做 Rendering Statistics Window , 即渲染数据统计窗口,它会实时统计数据。
-
FPS(Time per frame andFPS)
-
frames per seconds 表示引擎处理和渲染一个游戏帧所花费的时间,该数字主要受到场景中渲染物体数量和 GPU 性能的影响,FPS 数值越高,游戏场景的动画显示会更加平滑和流畅。
一般来说,超过 30FPS 的画面人眼不会感觉到卡,有视觉残留的特性,光在视网膜上停止用后人眼还会保持 1/24 秒左右的时间,因此游戏画面每秒帧数至少要保证在 30 以上。
另外,Unity 中的 FPS 数值仅包括此游戏 Scene 里更新和渲染的帧,编辑器中编辑的 Scene 和其它监视窗口的进程不包括在内。
-
CPU
- 获取到当前占用 CPU 进行计算的时间绝对值,或时间点,如果 Unity 主进程处于挂断或休眠状态时,CPU time将会保持不变。
-
Render thread
- GPU 渲染进程处理图像所花费的时间,具体数值由 GPU 性能来决定。
-
Batches
即 Batched Draw Calls, 是 Unity 内置的 Draw Call Batching 技术。
- 一般来说,引擎每对一个物体进行一次 DrawCall,就会产生一个 Batch,这个 Batch 里包含着该物体所有的网格和顶点数据,当渲染另一个相同的物体时,引擎会直接调用 Batch 里的信息,将相关顶点数据直接送到 GPU, 从而让渲染过程更加高效,即 Batching技术是将所有材质相近的物体进行合并渲染。
对于含有多个不同 Shader 和 Material 的物体,渲染的过程比较耗时,因为会产生多个 Batches。每次对物体的材质或者贴图进行修改,都会影响 Batches 里数据集的构成。因此,如果场景中有大量材质不同的物体,会很明显的影响到 GPU 的渲染效率。有关 Batches 优化相关的方案:
1、 虽然 Unity 引擎自带 Draw Call Batching 技术,我们也可以通过手动的方式合并材质接近的物体;
2、尽量不要修改 Batches 里物体的 Scale, 因为这样会生成新的 Batch。
3、为了提升 GPU 的渲染 效率,应当尽可能的在一个物体上使用较少的材质,减少 Batches 过多的开销。
4、对于场景中不会运动的物体,考虑设置 Static 属性,Static 声明的物体会自动进行内部批处理优化。
-
SetPass calls
- 在 Unity4.x 和 3.x 原来的 Stats 面板的第一项是“Draw calls”,然而到了 Unity5.X版本, Stats 上没有了“Draw calls”,却多出来一项“SetPass calls”。
比如说场景中有 100 个 gameObject,它们拥有完全一样的 Material,那么这 100 个物体很可能会被 Unity 里的 Batching 机制结合成一个 Batch。所以用 “Batchs”来描述 Unity 的渲染性能是不太合适,它只能反映出场景中需要批处理物体的数量。
那么可否用 “Draw calls”来描述呢?答案同样是不适合。每一个“Draw calls”是CPU发送个 GPU 的一个渲染请求,请求中包括渲染对象所有的顶点参数、三角面、索引值、图元个数等,这个请求并不会占用过多的小号,真正消耗渲染资源的是在 GPU得到请求指令后,把指令发送给对应物体的 Shader, 让Shader 读取指令并通知相应的渲染通道(Pass)进行渲染操作。
假设场景中有 1 个 gameObject ,希望能显示很酷炫的效果,它的 Material 上带有许多特定的 Shader。为了实现相应的效果,Shader 里或许会包含很多的 Pass,每当GPU 即将去运行一个 Pass 之前,就会产生一个 “SetPass call”,因此在描述渲染性能开销上,“SetPass calls”更加有说服力。
-
Batches and DrawCall
这个是绘制图像的重要指标,可以作为衡量场景绘制效率的首要参考。
-
一个 Draw Call, 等与呼叫一次 DrawlndexedPrimitive(DX) or glDrawElements(OGL),等于一个 Batch。
NVIDIA 在 GDC 上曾提出 25k batch/sec 的渲染量会使 1GHz 的 CPU 达到 100% 的使用率,因此使用公式: -
可以推算出某些 CPU 可以抗多少 Batch。例如红米手机 CPU 为 1.5Hz, 假设分出 20% 资源供渲染,希望游戏跑到 30 帧 。那么能抗多少 DrawCall ? 25k * 1.5 * 0.2 / 30 = 250。 因此从这方面也能看出,如果 CPU 不能分出更多的资源供渲染计算,能抗的 D人awCall 就会变少。
在 Stats 面板中看到的 Batches 是渲染的总 Batch 这个值等于同于 DrawCall。 但 Unity 中可以获取到末批次处理之前的 DrawCall。 因此需要注意不要混淆感念。
25K∗n(GHZ)∗Percentage/Framerate=Batch/Frame
-
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。 但为了将元素合并到一个大模型中,这项技术需要额外的内存。主要的内存消耗在于共享多边形会在内存中重复创建。因此有时候需要牺牲渲染效率来避免静态合并,来保证内存够小。例如在茂密的树林中使用这项技术会导致大量的内存消耗。
-
Verts
- 摄像机视野(field of view)内渲染的顶点数。 Tis
- 摄像机视野(field of view)内渲染的三角面总数量。
关于 Tris 和 Verts
1、 Camera 的渲染性能受到 Draw calls 的影响。之前说过,对一个物体进行渲染,会生成相应的 Draw call,处理一个 Draw Call 的时间是由它上边的 Tris 和 Certs 数目决定。尽可能得合并物体,会很大程度的提高性能。举个很简单例子,比如场景一种有 1000 个不同的物体,每个物体都有 10 个 Tris; 场景二中有 10 个不同的物体,每个物体有 1000 个 Tris 。 在渲染处理中,场景一中会产生 1000 个 Draw Calls,它的渲染时间明显比场景二慢。
2、Unity stats 视图中的 Tris 和 Verts 并不仅仅是视锥中的梯形内的 Tris 和 Verts,而是 Camera 中 field of view 所有取值下的 tris 和 verts,换句话说,哪怕你在当前 game 视图中看不到这个 cube, 如果当你把 field of view 调大到179 过程中都看不到这个 cube,stats 面板才不会统计, GPU 才不会渲染,否则都会渲染,而且 unity 不会把模型拆分,这个模型哪怕只有 1 个顶点需要渲染, Unity 也会把整个模型都渲染出来。(参考自Mess的《Unity Camera组件部分参数详解》)
3、新建一个空的场景,里面没有添加任何物体,为什么 status 面板上显示有 1.7k Tris 以及 5.0k Verts 。这是因为空的场景自带默认的天空盒、Windows—>Lighting打开 Ligh下的 Scene 面板,把 Skybox 里的材质设为空。删掉它,就会发现 Tris 和 Verts 都会变为0了。
-
Scree
- 获取当前 Game 屏幕的分辨率大小,后面的 值 表示总的内存使用。
-
Shadow casters
- 表示场景中有多少个 可以投射阴影的物体,一般这些物体都作为场景中的光源。
-
Visible skinned meshed
- 渲染皮肤网格的数量。
-
Animations
- 正在播放动画的数量。
脚本获取值
在编辑模式下这些数据是可以通过脚本获取到的,不过打出包来不太成,代码如下:
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);