如何在U3D中合理的使用资源【总结】
1.纹理资源
1.1 纹理资源的格式对加载性能影响较大,Android平台上,ETC1和ETC2的加载效率最高。同样,iOS平台上,PVRTC 4BPP的加载效率最高。
1.2 RGBA16格式纹理的加载效率同样很高,与RGBA32格式相比,其加载效率与ETC1/PVRTC非常接近,并且设备越好,加载开销差别越不明显。
1.3 RGBA32格式纹理的加载效率受硬件设备的性能影响较大,ETC/PVRTC/RGBA16受硬件设备的影响较低。
1.4 就笔者发布时间来看,现在都安卓机都已经支持OpenGL ES3.0,而IOS是从A8开始支持 ASTC,然后再来看看市场占有率。
结论:安卓推荐使用ETC2,IOS推荐ASTC。
2.纹理分辨率
分辨率推荐大家控制在1024*1024以内,如果超过尽量分图集来实现,2048*2048这样的纹理更容易产生空白区域,而空白区域也占内存,还会影响加载。
3.Mipmap
3.1 开启Mipmap功能会导致资源加载更为耗时,且设备性能越差,其加载效率影响越大。
3.2 一般来说UI的纹理资源不会使用到Mipmap功能,记得要取消勾选。
3.3 而模型的纹理资源Mipmap一般是要开的。Mipmap可以提高纹理Cache连续性,即提升Cache的命中率,也提升了纹理采样的速度。另外开了Mipmap,可以在Mipmap level之间进行三线性滤波,可以使纹理放大缩小的时候,画面更细腻。简单说就是能提升渲染效率和画面表现。
4.网格优化
4.1 规范美术需求,在美术可以接受的前提下,尽可能降低网格资源的顶点和面片数量。
参考标准:
动态物体,角色、怪物、NPC
(1)控制面的数量,300-2000个
(2)控制Skinner Mesh Renderer的数量,1个
(3)控制材质数量,1-3个
(4)控制骨骼的数量,小于30个
静态物体
(1)控制网格顶点数,少于500个
(2)标记为static,静态批处理
(3)移除不需要的组件
自带地形
(1)控制地形的分辨率,高度图尺寸小于257
(2)地形纹理中尽量使用少的混合纹理数,不要超过4个
4.2 对于顶点属性的使用需谨慎处理。根据项目经验总结出,顶点属性越多,则内存占用越高,加载时间越长。
注意事项:
模型常见的顶点属性主要有Position、UV、Normal、Tangent和Color。特别需要注意Color和Tangent属性,如果网格顶点拥有该属性,会对内存、物理体积和加载性能造成影响。
并且使用Draw Call Batching时,切忌将不同属性的网格模型拼合在一起。举个例子 ,100个网格模型进行Static Batching,如果99个模型只有Position和UV两种属性,而剩下1个模型函数有Position、UV、Normal、Tangent和Color五种属性。那么引擎在进行拼合时,会将前99个模型的顶点属性补齐,然后再进行拼合。这样无形中会增加大量的内存占用,从而造成不必要的内存浪费。
4.3 如果在项目运行过程中对网格资源数据不进行读写操作(比如Morphing动画等),那么建议将Read/Write功能关闭,既可以提升加载效率,又可以大幅度降低内存占用。
5.动画资源
5.1 压缩格式。Unity引擎对导入的AnimationClip提供三种压缩格式,Off、Keyframe Reduction和Optimal。其中,Off表示不采用压缩处理;Keyframe Reduction表示使用关键帧进行处理,Optimal则表示Unity引擎会根据动画曲线的特点来自动选择一个最优的压缩方式,可能是关键帧压缩,也可能是Dense压缩。Optimal压缩可以提升资源的加载效率,无论是在高端机、中端机还是低端机上,硬件设备性能越好,其加载效率越高。但随着设备的提升,Keyframe Reduction和Optimal的加载效率提升已不十分明显。另外,Optimal压缩方式可能会降低动画的视觉质量,因此,是否最终选择Optimal压缩模式,还需根据最终视觉效果的接受程度来决定。
不过一般来说推荐大家使用Optimal来压缩。
5.2 动画类型。Unity里有两种动画类型Humanoid和Generic。排除两种类型的功能来比较,Humanoid的内存占用和文件大小都会比Generic要小,加载也更快。而Generic的优点是运行时性能会有提升。需要注意的一点说模型变到Humanoid,骨骼会有空间转换以及中间骨骼的插值,所以可能会造成位置信息的不完全对应。这点大家可以根据实际情况测试后作出选择。
5.3 压缩AnimationClip文件float的精度,建议优化float的精度到三位,一般目测不出差别,但是无论是文件大小和内存占用都会减少很多。
5.4 去掉AnimationClip中的无效数据:例如模型不需要缩放的话,可以去掉ScaleCurve这样的缩放信息。
5.5 简化骨骼名称。这点很容易在优化中被忽略,unity的动画数据存储的时候按每个骨骼节点的轨道拆分存储的,每个骨骼存储的是从根节点到这个骨骼节点的hierarchy路径,字符串的,骨骼多了之后这部分字符串不少。如果把所有骨骼名字都简化,这里可以省不少内存 。这里需要跟美术人员好好沟通。
6.Shader资源
Shader的物理体积和内存占用虽然很小,但其加载耗时的CPU占用很高。这是因为Shader的解析开销很高,这成了Shader资源加载的性能瓶颈。而且在高低端机型的表现上差距非常明显,性能越低,性能差距越大。
Shader的加载开销经常在几百甚至上千毫秒以上,所以在项目规划时,尽量别在非切换场景时加载shader。
6.1 优化keyword数量。一般情况下,Shader加载的CPU耗时与其Keyword数量有关,Keyword数量越多,则加载开销也越大。我们要做的是根据实际情况,通过skip_variants操作在Shader中去除没有用到的Keyword。(需要对Shader具备一定的了解有才能针对的去除)
6.2 尝试去除Shader中的Fallback选项。Fallback功能是对于无法使用当前Shader的硬件设备可以使用对硬件设备要求更低的Fallback Shader来进行渲染,以保证渲染的稳定性。而实际情况是,不支持Mobile/Diffuse和Mobile/Bumped Diffuse的设备几乎不存在。因此,对于使用Mobile Shader的项目,可以尝试直接将其FallBack去掉,这样会大幅降低Keyword,降低Shader的解析时间,进而提升加载效率。
6.3 对Shader进行单独、依赖关系打包并对其进行预加载,以降低后续不必要的加载开销。每次切换场景时,Shader加载均占用大量的CPU耗时,实际上是大量相同Shader重复解析造成的。究其原因,是因为Shader被打包到不同的AssetBundle文件中,每次切换场景时,AssetBundle均会被频繁地进行加载和卸载,从而造成了大量相同的Shader被重复加载和卸载,所以对Shader打包,设置依赖关系,单独预加载非常有必要。
7.音频资源
7.1 首先建议使用MP3格式文件,物理体积最小。
7.2 背景音乐建议使用Streaming加载方式。
7.3 如果非实时音效,建议使用Load In Background来提升加载效率。
7.4 如果存在大量频繁使用的音效,建议选择Decopressed On Load来降低CPU开销。
8.粒子系统
8.1 材质剥离。将粒子系统的材质剥离出来,设置好依赖关系提前加载,这样可以过滤掉大量粒子相同材质的重复加载。不剥离的话,每个材质单独加载都会有耗时,粒子越多,优化空间越大。
8.2 打包加载。如果项目中使用的粒子不是很多的情况下,可以将所用到的粒子,集中打包批量加载。因为粒子的量级并不大,所以并不会占用太大内存,但是加载效率会提升很多。如果多的话,可以根据场景或者关卡分批打包加载。
如果喜欢本文请点个❤,或者赞赏支持一下。
码字不易,转载请附上原文链接,谢谢。