Unity优化笔记——内存优化

Unity游戏的内存主要划分为Unity占用、第三方库占用和系统层面的占用三部分,而我们影响的最主要的是Unity层面的。

Unity层面主要分为资源、引擎native占用和临时对象三部分,我们分别从这三个部分分别进行优化。

  • 资源优化:

资源优化主要分八个模块进行:贴图资源、模型资源、动画资源、声音资源、粒子特效、shader、脚本、配置文本。其中贴图、模型、动画和声音作为最常用的资源,主要的处理方式是有损资源压缩(例如贴图压缩成ETC/PVRTC格式进行硬件加速;模型使用unity内置的压缩进行,将临近的顶点进行删减;动画将临近的关键帧删除;声效压缩成ogg格式等)。但是仅仅这样是不够的,而且会出现一些问题,比如安卓在OpenGL2.0上带通道的贴图没办法进行ETC格式的压缩,IOS上压缩成PVRTC格式后的质量也是不够的。针对这些情况,可以将带alpha通道的贴图进行alpha拆分,拆分之后可以分别对RGB贴图和alpha贴图进行压缩,这样对于压缩之后的贴图的品质也会有一定的提高。

针对于动画文件,unity的动画文件往往会有一些冗余的帧和冗余的轨(比如在动画中某些骨骼一直保持不动,这时候美术在动画制作的过程中往往会将关键帧K满,这样往往会有一些直线的轨出现),这是关键帧中的一些冗余数据是可以删除的,我们通过解析Unity中的Animation文件可以找到一些冗余的关键帧,将它们删除就可以了。

对于粒子系统,每一个粒子系统实例要占到10K左右的内存,但是由于使用粒子系统在展现效果上比传统的使用面片或动画做出来的效果要好很多,因此美术更偏爱于使用粒子系统。但是从手机的性能考虑,要严格限制粒子系统的质量。

在使用shader尤其是从网上找到的shader时要注意里面的一些坑,比如有些shader中包含了很多效果,但是我们需要用到的只有其中一个,还有就是shader中包含了很多预编译的宏。如果对每一个shader都进行编译的话,这些没有被使用的代码也会编译成shaderProgram占用额外的内存。

至于脚本和配置问本,只需要注意及时卸载就好。

整体来说,资源优化最重要的一点就是做好LOD。

  • 引擎native占用优化:

引擎占用主要在AB层面的占用和Mono堆的占用。为了节省内存和热更新,几乎所有的手游都会打AB,AB的加载策略和打包策略都会影响到对内存的占用;而Mono堆更是对内存最主要的占用之一。

AB包最主要的问题就是如何处理公共资源,在打包策略上通常有脚本全自动打包和纯手动打包两种。

全自动打包可以通过程序自动处理资源的依赖关系,凡是公共的资源就打成公共的AB包。可是这样公共的AB包就会非常多,为了减少加载时的IO要对公共的AB进行合包。一般一个ab包在10M以内比较合适。但是全自动打包的问题也是比较明显的,在热更新中哪些ab发生了怎样的变化并不直观,变向增加了管理成本。

扫描二维码关注公众号,回复: 4673621 查看本文章

纯手动打包需要有明确的需求,并且要求逻辑分割明显,比如Moba类的游戏,可以将一个英雄的相关资源打在一起,这样打出来的包更简便,也不需要做合包这种事。这样做的优点是逻辑清晰,明确知道哪些ab会发生变化,但是问题同样很明显:因为是手动打包所以后期需要人力成本维护,并且在项目前期需要及早的进入资源的规划和管理中来。

因此在打包策略上需要根据项目的实际情况适当的将两种打包策略结合使用。

AB的加载策略优化的主要方向是优化内存峰值,减少同时存在的资源路径数量。因为AB文件头中保存了这个AB中所有资源相关的路径信息,加载AB的时候这些信息会加载到内存中来。资源路径相关的信息可以在Profiler中的PersistentManager和passname这两项中看到。PersistenManager类似于mono堆的机制,峰值一堆上去就不会再释放,所以对于峰值的优化尤为重要。主要方法是解析场景中需要加载的资源的依赖关系,将同样依赖关系的资源尽量一起加载。这样可以尽快卸载掉公共的AB包,确保同时存在的AB的数量是最小的。

Mono堆一般分为场常驻和瞬时分配两种。常驻一般由于static变量和singleton单子发生的内存分配产生。这块的分配非常细碎分散,处理不好可能会对项目的延展性产生较大的影响。这里推荐使用腾讯的wetst工具进行分析,具体的分析和优化思路可以参考大佬的文章http://gad.qq.com/article/detail/20966。瞬时分配可以通过Profiler进行排查,并且平时要注意代码规范。

  • 场景中的临时内存的优化:

临时内存分为UI、Particle Instance、Batched Mesh三部分,UI会在背后产生一些不被察觉的mesh,所以要尽量减少UI的复杂度;特效在运行时复制很多份会导致大量的particle实例产生,此时要使用对象池规划并减少particle实例的峰值;美术在使用合批工具时也会带来合并mesh的内存消耗,所以需要合批的mesh需要美术在线下完成。

第三方库在unity层面是无法监控和处理的,所以优化方法主要是延迟第三方库的加载时间,用到了才去加载。并且注意做好模块分离,这样可以在第三方库内存占用过大或者内存泄漏时使用模块隔离的方式快速确定是哪个库出的问题。

 

 

猜你喜欢

转载自blog.csdn.net/qq_39029746/article/details/85277079