一、资源优化
1、贴图
贴图优化是大头,因为一个游戏内存最多的基本都是贴图了,所以贴图优化很重要。
(1)是用PackingTag打包贴图,因为一张贴图大小如果不是2的n次幂,unity会补全,这时候有很多地方是空的,利用这个工具可以把多个小的贴图挤进那些空白的地方。为了节省内存,已经不只是补全空白位置,把多张贴图打包成一张大的贴图,也可以大大减少小贴图浪费的那些空白内存。同时对内存也有优化,游戏中贴图被加载进内存,一次加载大贴图比一张一张加载小贴图使用更少内存。
(2)把透明贴图和不透明贴图分开打包,透明贴图有透明通道,占用比较大内存,如果一张贴图不是透明的就不要使用有透明通道的压缩格式了。
(3)小心勾选Read/Write Enabled
勾选这个是为了能在游戏中动态修改图片,比如我实习的时候开发的填色游戏:
这样会让贴图的大小增大一倍。
2、短的音频可以使用 .wav/.aif等未压缩格式,比如打击的声音。
二、动态物体
1、手游面片2000-3000个就够了(虽然我觉得这是美工的技术活,不过学到了就写上来把)
2、控制材质数量
材质数量就意味着DrawCall,一次DrawCall就是CPU给GPU设置渲染状态,传递渲染参数,并调用一次GPUAPI进行渲染,有时候渲染中拖后腿的不是CPU而是GPU,当渲染内容很小时GPU可以很快的完成一次渲染,然后等待CPU慢慢的设置渲染状态,所以DrawCall越少,意味着一次渲染的内容更多,把时间平衡到GPU上,这样CPU和GPU都能充分使用。
三、静态物体
1、标志为Static Batching,Unity会使用合并这些网格,对于GPU来说渲染100个网格和1000个网格差不了多少,重要是CPU设置渲染状态相对比较慢,如果把更多的网格使用一次设置去渲染,效率就提高了。
2、静态物体不要加Animation组件,之前做地下城冒险的时候,一个河流是Animation来模拟水流,帧数很低,可以改成修改贴图的offset来模拟河水流动。
3、使用MipMap,给贴图生成不同清晰度的贴图,当距离比较远的时候将使用清晰度比较低的贴图,提高渲染效率但是贴图的大小一般会增大33%
4、使用LOD,多层次细节,和MipMap差不多,越远看到的模型越粗糙,不同的是不同精度的模型要自己准备,在Unity中改变模型的距离是要自己控制的,所以要掌控好距离,在地下城冒险的时候我就掌控不好,会出现模型大于某个距离突然消失,小于某个距离又突然出现的情况,可以参考一下龙之谷主城的草,不仔细看真的看不出是走近才出现的。缺点也一样,本来只要一个模型,现在却需要更多的模型,使用了更多内存。
5、使用遮挡剃除技术,就是看不到的顶点剔除掉,猜测是使用算法修改CPU传入GPU的顶点数据,只传入那些看到的顶点,所以需要CPU做额外的计算。因为深度测试模板大多数是在片元着色器之后的,就是说之前做了很多计算到这里发现是看不到的就把之前的计算结果都抛弃了,所以看不到的物体依然会被计算,只是在屏幕看不到而已,使用遮挡剃除技术把看不到的先剃除,可以减少顶点计算和DrawCall。
6、共享材质,静态批处理的物体要求使用的是同一种材质,批处理才有效,如果要对不同的物体进行批处理,则可以把他们的贴图打包成一张贴图,然后对不同的纹理坐标采用即可。这也他们就可以使用同一个材质了。
三、引擎优化
1、少用透明物体,一个真正的透明物体是需要能通过自己看得到自己的背面的。
右图才是正确的效果,为了保证透明物体从后往前渲染,需要两个Pass来渲染,一个渲染背面,一个渲染正面。而且最关键的一点是容易造成像素点的过度渲染(OverDraw),就是我一个像素点只要渲染一次,但是由于透明物体关闭深度写入,所以所有在不透明物体前面的物体都会被渲染,当多个透明物体重叠了,他们在屏幕上前后重叠的部分会被重复渲染。场景中尽量少用透明物体,有的话尽量减少透明物体之间的重叠。(下图红框为重叠部分)
2、粒子特效
半透明而且贴图缩放值较大的粒子特效特效会特别消耗性能,除了多次调用DrawCall还过度渲染。所以粒子特效少用透明的,尽量减小粒子特效的贴图缩放值从而减少重复渲染。
3、灯光
灯光下RenderMode可选Important选项,尽量控制在一个一下,Unity会为Important的光源采用逐像素处理,每一个Important光源都会渲染一次,叠加在之前的结果上,所以要减少Important光源的数量。可以使用烘焙来生成光照纹理,如果需要实时阴影,可以使用Camera+RenderTexture来生成阴影。
4、控制渲染顺序,减少OverDraw
不透明物体的渲染队列是从前往后渲染的,这样的好处是后面的物体在深度测试的时候抛弃而不会写入深度缓存和帧缓存,利用这个思想我们可以让最前面的东西先渲染,比如第三人称的一些游戏角色总是占据屏幕的一大部分,所以可以先渲染游戏角色,再渲染其他,天空盒占据了整个屏幕,所以可以最后渲染,避免减少OverDraw。
5、相机设置合理的裁剪平面(near far。。。之类的)
6、少用MeshCollider,精细的计算需要更多的时间。
四、代码优化
1、改除法为乘法
这个结果还是比较明显的吧,大概快一倍吧。
2、定期回收垃圾
在GC回收垃圾的时候所有的托管线程都会停止运行,如果这个执行时间比较长玩家会察觉到卡顿,所以可以定期执行,把GC运行时间分散。比如50帧就回收一次垃圾。
3、少在Update和OnGUI使用局部变量,频繁入栈出栈也是很浪费时间的。
4、如果Update函数是空的就清掉,不要留在那里,有Update计算里面没有东西也是要执行的。
5、适当情况下使用对象池,老生常谈了。