首页 > 代码库 > Unity3D-优化相关
Unity3D-优化相关
Unity每次在准备数据并通知GPU渲染的过程称为一次Draw Call。一般情况下,渲染一次拥有一个网格并携带一种材质的物体便会使用一次Draw Call。每一次Draw Call中,除了在通知GPU渲染上比较耗时之外,切换材质和Shader也很耗时。Draw Call是决定性能的重要指标,最好控制在20以内,可以在Game窗口中点击上方的Stats来查看。
Draw Call Batching:每运行一次Draw Call时,批量处理多个物体。对于场景中的每个物体,只要它们的材质相同,GPU就可以按完全相同的方式处理。该技术的核心是在可见性测试后,检查所有要绘制物体的材质,把材质相同的游戏对象分成一组(Batch),这样就可以在一个Draw Call中处理多个物体。
Static Batching:静态批处理。允许对任意大小的几何物体批处理以降低Draw Call次数,前提是这些物体始终保持静止状态,并拥有相同材质。静态批处理比动态批处理更加有效,对CPU的消耗更小。使用静态批处理需要额外的内存消耗来存储合并后的几何数据。
Dynamic Batching:动态批处理。如果游戏场景中的动态游戏对象(包括位移、旋转、缩放)共用相同的材质,那么Unity会自动对这些物体进行动态批处理操作。
(1)动态批处理的物体需要在每个顶点上进行一定的开销。所以动态批处理仅支持小于900个顶点的网格物体。如果着色器需要用到顶点的位置、法线和UV值3种属性,则只能处理300个顶点以下的物体;如果用到顶点位置、法线、UV0、UV1和切线向量,则只能处理180个顶点以下的物体。
(2)统一缩放的物体不会与非统一缩放的物体进行批处理操作。例如,使用缩放尺度(1,1,1)与(1,2,1)的两个物体不会批处理;但使用缩放尺度(1,2,1)与(1,3,1)的两个物体可以进行批处理操作。
(3)拥有lightmap的对象有一些隐藏的材质属性,所以不会进行批处理操作。
(4)多个Pass的Shader会妨碍批处理操作。
(5)接受阴影的物体不会进行批处理。
1. 尽量避免在Update函数里使用GetComponent来获取组件,这个操作比较耗时,应该在初始化时把组件的引用保存在变量中。
2. 使用CompareTag来比较tag是否相同
3. 尽量避免使用MeshCollider
4. 使用遮挡剔除来提升性能
5. 使用lightmapping来替代实时光照,提升性能
在Build游戏时,打开Build Settings中的Player Settings,选择Other Settings会看到很多选项。如果你想优化游戏,一定要注意这里。Dynamic Batching是自动进行的,对于顶点数在300以内的可移动物体,只要使用相同材质就会组成Batch。Static Batching这需要你预先把静止的物体标记为static,然后无论大小,都会组成Batch。所以,static batching显然比dynamic batching更加高效。你可以点击Game视口中的Stats,通过draw calls的大小可以看出性能的变化,当我同时去掉static batching和dynamic batching时,性能最好。想要查看内存和CPU使用情况,可以打开菜单栏中的Window->Profiler工具。
在PlayerSettings中,勾选Optimize Mesh Data可以减小安装包的体积,勾选Dynamic Batching也可能减小安装包的大小,将Strpping Level变为Use micro mscorlib可以明显减小安装包的大小。在Projects->Quality中可以调整默认的图像显示级别,从而提升性能,但效果不怎么明显。
Android优化时,如果使用了NGUI,通过将atlas对应的整张png图片进行优化,可以明显改变apk的大小。常见的方法是,将texture type类型改为advanced,然后改变最下面的format为RGBA Compressed PVRTC 4 bits,看到Inspector面板,在右下角的preview中可以看到图片大小已经变得很小了。体积虽然减小了,但内存占用可能提升了。
IOS版优化时,如果用了NGUI,必须要把format改为RGBA Compressed ETC2 8 bit才行,我开始用了其它的方式都不好,用ASTC 6X6 block后在iphone4s上会黑屏。但是,我的游戏异常崩溃了,是由内存占用太多导致的。最后,我试着放弃了这种优化,把format改成了原始的RGBA 16-bit,内存占用就少了很多。