Unity优化性能的方法有:包体体积优化、骨骼动画优化、LOD的优化、模型细节增强,提升计算性能、 光照优化、SetPassCall与Drawcall优化、物理引擎的优化、阴影的优化、Shader优化等。
1、包体体积优化
声音文件优化: 将wav,压缩成mp3或ogg, 最好是ogg,没有版权问题, 将多声道变成单声道。改变声音的采样率与码率,减少声音文件体积。
贴图文件大小优化: 将png转jpg, 并使用图片压缩软件,压缩贴图体积, 尽量减少图片数目,复用图片,尽量能使用颜色等代码的方式来代替贴图。
3D模型文件: 根据需求适当降低模型面数, 去掉多余不用的数据, 可以通过法线贴图,高度贴图等将低模做出高模的效果, 合并贴图通道数据(PBR工作流中,将金属度,粗糙度,环境遮挡放一个纹理里面, 将数据合并到贴图不用的通道,比如Albedo贴图,Alpha通道不用,就可以存放环境遮挡等,节约贴图数目)
将资源ab包化: 把所有的资源分成一个一个的ab包,ab包本省有压缩功能,这样整体的包体也会减小,如果可能,可以把ab包全部放服务器,第一次运行游戏的时候再下载,比如《王者荣耀》,来节省包体体积。
2、骨骼动画优化
3D游戏中骨骼动画也是非常消耗性能的地方,因为每帧,我们都要通过动画组件采样,采样后重新计算出来我们的顶点的位置,传给GPU的渲染管线来处理, 我们可以将骨骼动画的每帧顶点的位置缓存到一个纹理贴图里面,用空间换时间的方式来节约动画组件的开销,并尝试合并Drawcall。
3、LOD的优化
对于大规模多角色的场景游戏,我们要开启LOD,让远处的问题用尽量少的面,近处的物体用更多的面。
4、模型细节增强,提升计算性能
使用法线贴图,高度贴图等细节增强手段来降低模型的面数同时,能获得和高模同样的细节和更好的计算性能。
5、光照优化
静态光照烘培+反射探头来做更好的场景效果,代替实时的光照计算,减少光源的数目。对于一些物体的发光特效,可以通过shader来实现,而不用加光源。定制Shader,可以将逐像素光照改为逐顶点光照,节约逐像素光照的计算开销。
6、 SetPassCall与Drawcall优化
SetPassCall:通俗的讲解就是更换重新装在渲染管线里面的Shader代码和配置,就像换画笔一样的。SetPassCall开销非常的大,所以尽可能的要少用一些不同的Shader,再一个场景里面。尽可能的让同一个Shader 绘制最多的物体后再切换下一个Shader。尽量避免绘制物体的时候平凡交叉的来回切换Shader来节约SetPassCall的次数。
Drawcall 优化,其实很简单三种优化手段,静态合批,动态合批,GPU Instancing合批, 然后我们针对合批的条件去达成对应的条件就可以了,比如,我们做一个捕鱼达人3D游戏,我们有很多的鱼,可以把鱼的所有纹理贴图,放到一个大图里面,这样,这些鱼就是同样的Shader,同样的纹理贴图对象,就可以达到合批的条件而做到合批, 节约Drawcall。
7、 物理引擎的优化
能不用物理引擎的游戏,尽量不用物理引擎,能用代码自己实现的尽量用代码自己实现,因为物理引擎的开销毕竟摆在那里了, 用了代码很简单,但是性能开销也不可忽视。有一些不是真正的物理游戏,比如Moba类的游戏,防止物体穿透等,其实我们可以不用物理引擎,通过制作地图格子的方式,标记障碍物,自己控制的时候,如果进入障碍物的标记,就不让他更新即可,这些可以替换物理引擎获得很好的性能效果。常用的有菱形的地图格子与六边形的地图格子。
暂时不用的刚体,或者不在视线范围内的刚体可以根据游戏的需要,来显示和隐藏,达到节约物理引擎计算的目的。修改物理引擎全局的迭代参数,获得实用性的同时又有更好的性能。了解物理碰撞器的性能开销,球体最小,网格碰撞器最大,尽量使用开销小的碰撞器, 对于静态物体,能够合并物理碰撞器的尽量用一个物理碰撞器。
8、阴影的优化
通过开关控制阴影,在低端机上关闭阴影获得更好的运行帧率,在高端机上开启获得更好的运行效果。通过伪阴影技术来做贴图,节约阴影计算的开销, 可以自己定制Shader来实现高性能的阴影效果。
9、Shader优化
减少Shader中的条件判断和展开循环,来获得更好的指令缓冲cache 命中率, 减少一些复杂的计算,可以采用一些空间换时间的方法来缓存计算结果。逐顶点计算来替代逐片元的计算,减少计算次数。可以把Shader 设置为常驻内存缓存,这样节约SetPassCall所带来的开销。
10、 C#编写代码的习惯
Update里面尽量不要使用GetComponent, Find等,可以在初始化的时候先找出来,然后在Update里面使用, 能不放FixedUpdate尽量不放FixedUpdate, 这样低端机上能节约计算次数。
能降低FixedUpdate计算时间间隔的,尽量减少计算时间间隔,能减少计算的次数。写代码的平常的一些规范就不说了,避免大量的new 对象。一些重复使用的对象,可以通过节点池等原理先缓存起来。可以采用多线程来做一些计算避免卡住游戏线程导致帧率下降。不要再游戏住线程里面直接做同步的IO以免卡住游戏线程,导致帧率下降,从开始写代码起,要把每行代码写好,长期的坚持积累,才能形成良好的代码习惯写出高性能的代码,最重要的是学好数据结构与算法等基础知识,好的算法是好性能的关键。