Unity3d|Unity3d Batched和Draw Call指的是什么()

在Unity开发过程中我们不可避免的要对我们的项目进行一些性能上的优化,那么究竟如何进行优化和要优化哪些东西是我们需要注意的?Unity其实为我们提供了很多优化性能的指标今天我们来看一下Batch 和Draw Call 这两个重要的性能指标。
什么是Batched和 Draw Call? 我们在使用unity的时候经常会要求尽量降低Draw call和Batched 的数量。那么Draw call 和Batched 到底指的是什么呢?
Draw Call: Unity生成一帧的画面的处理过程大致过程是:引擎经过可见性测试,确定摄像机可以看到的物体,然后把这些物体的顶点(包括顶点位置、法线、uv 等),索引(如何组成三角形),变换(物体的位置 旋转 缩放 以及摄像机的位置)相关光源,纹理,渲染方式(由材质/Shader决定)等数据准备好 然后通知图形API(或者就简单地看作是通知GPU)开始绘制,GPU基于这些数据经过一些列的运算,在屏幕上画出组成图形的三角形,构成一幅画。在unity 中每次引擎装备数据并通知GPU的过程为一次Draw Call。
Batched: Batched 其实是Draw Call的另外一种称呼。你可以想象成 每一次的Draw Call 是CPU把一个Batched里的数据(物体的顶点数据)传输给GPU,由GPU绘制到屏幕上。因此Batched越多需要传输的数据就越多,产生的Draw Call也会越多(这里需要注意的是 Unity内部有优化机制Dynamic Batching 这是自动进行我们下次会重点介绍 ,这次先不做陈述)也会消耗更多的性能。
如何优化Draw Call? 前面提到Unity每一的Draw Call CPU都要经过大量的运算 来收集数据,然后传输给GPU进行渲染绘制。由于GPU内部结构的构成可以进行大规模的相互无依赖的数据的运算,所以同事进行多个Draw Call 的渲染压力不大。CPU不但收集要渲染物体的数据还要进行大规模的预算。所以一帧内同事渲染Draw Call 数量的增加会造成CPU的压力增大。那么如何对Draw Call数据进行优化。
Unity 内置了一个Draw Call Batching 的技术。它的主要目的是在同一次Draw Call 中批处理多个物体。只要物体的变换和材质相同,GPU就可以按完全相同的方式进行处理,即可以把它们放在一个Draw Call中。
Draw Call Batching技术的核心就是在可见性测试之后,检查所有要绘制的物体的材质,把相同材质的分为一组(一个Batch),然后把它们组合成一个物体(统一变换),这样就可以在一个Draw Call中处理多个物体了(实际上是组合后的一个物体)。

但Draw Call Batching存在一个缺陷,就是它需要把一个Batch中的所有物体组合到一起,相当于创建了一个与这些物体加起来一样大的物体,与此同时就需要分配相应大小的内存。这不仅会消耗更多内存,还需要消耗CPU时间。特别是对于移动的物体,每一帧都得重新进行组合,这就需要进行一些权衡,否则得不偿失。但对于静止不动的物体来说,只需要进行一次组合,之后就可以一直使用,效率要高得多。(所以什么东西都是相对而言的,这里就表明并不是把所有的Batched 都合并在一起 通过一次Draw Call 绘制出来就是好的。我们我在一定的范围内进行Batched的合并)

Unity提供了Dynamic Batching和Static Batching两种方式。Dynamic Batching是完全自动进行的,不需要也无法进行任何干预(这里我们前面已经说说过,但是这里需要注意的是 Dynamic Batching 的合并除了在使用形同的材质和形同纹理文件还跟收集文件的方式有关,比如NGUI 就是通过深度来判断是否将相邻的两个batched 是否合并),对于顶点数在300以内的可移动物体,只要使用相同的材质,就会组成Batch。Static Batching则需要把静止的物体标记为Static,然后无论大小,都会组成Batch。如前文所说,Static Batching显然比Dynamic Batching要高效得多。

要有效利用Draw Call Batching,首先是尽量减少场景中使用的材质数量,即尽量共享材质,对于仅纹理不同的材质可以把纹理组合到一张更大的纹理中(称为Texture Atlasing)。

然后是把不会移动的物体标记为Static。此外还可以通过CombineChildren脚本(Standard Assets/Scripts/Unity Scripts/CombineChildren)手动把物体组合在一起,但这个脚本会影响可见性测试,因为组合在一起的物体始终会被看作一个物体,从而会增加GPU要处理的几何体数量,因此要小心使用。

对于复杂的静态场景,还可以考虑自行设计遮挡剔除算法,减少可见的物体数量同时也可以减少Draw Call。









【Unity3d|Unity3d Batched和Draw Call指的是什么()】






    推荐阅读