最新文章
泰课在线 | 微信拼团成功后如何获取课程?
08-09 17:57
Unity教程 | 使用ARKit为iOS开发AR应用
07-31 17:23
Unity Pro专业版7折订阅四选一工具包之VR开发与艺术设计
07-28 11:47
网友使用虚幻UE4实现CAVE 多通道立体渲染的沉浸式环境
07-27 11:57
VR晕动症调查:未来5年内大部分VR晕动症将得到解决
07-27 11:26
AMD CEO:未来3-5年最重要 希望5年达1亿VR用户
07-27 10:44
如何优化AssetBundle资源
听说你的项目仅这些资源就卡顿严重?看看他们是怎么做的!项目中的冗余资源不仅会在项目文件中占据额外空间,还可能在内存中被多次加载,占用大量内存。笔者借助 UWA 提供的资源检测与分析功能,精准定位了所有 AssetBundle(下文简称 AB)中包含的冗余资源,并轻松对这些资源进行了定点优化。下面让我们详细了解实现步骤。
目录
- 目标
- 检查
- 迭代优化
- 额外收益
- 结合 Unity Profiler 优化内存占用
- 总结
一、目标
优化 AB 具有多方面的重要意义。一方面,能够降低 AB 的大小以及包体大小;另一方面,可以减小 AB 加载时所占用的内存,从而降低游戏因内存不足而崩溃的概率。同时,通过对 AB 中包含资源的深入分析,还能避免将一些旧的资源错误地打入到 AB 中。
二、检查
1. AB 打包方式及策略
Unity 4.x 的 AB 打包采用手动管理依赖的方式,这种方式如同 C 语言直接使用指针,虽然控制性强,但极易出错,操作起来非常麻烦。而 Unity 5.x 实现了自动管理 AB 之间的依赖,大大减轻了开发负担。不过,自动管理依赖也容易导致开发者对 AB 资源打包原理缺乏深入分析和关注,进而使得对 AB 的优化不够到位。
打包的基本策略是将公共依赖的资源打入到一个公共 AB 中,其他 AB 依赖于该公共 AB。我们使用的是 Unity 5.x,在 Unity 5.x 中打包 AB 有两种方式:一种是直接在编辑器中为每个资源设置其所属于 AB 的名字;另一种是在代码中设置每个 AB 包含哪些资源路径。我们采用的是第二种方式,即在代码中指定。
2. UWA 资源检测及问题发现
我们在 UWA(www.uwa4d.com)上提交了若干次资源检测,逐步优化了一些 AB 打包中的问题。UWA 中的 AB 资源检测界面主要分为两个栏目:一个是以 AB 为观察对象,另一个是以资源本身为观察对象。
第一次检测结果显示,很多 AB 中有冗余的资源。点击“资源使用”栏目,可以查看哪些资源出现了冗余,通常冗余的资源包括 Shader、材质、纹理、Sprite、动画等。
我们还能看到资源冗余的具体情况。例如,有大量的 Sprite 冗余,原因是我们游戏的每个 UI 都单独打了一个 AB 包,而 UI 公共使用的一些 Sprite 没有打入到公共 AB 中,导致这些 Sprite 被打入到了每个 UI AB 中,其对应的纹理也被打入到了这些 UI 的 AB 中。解决方案是额外添加一个公共 AB,将这些 Sprite 打入其中,使 UI AB 依赖于这个公共 AB。
以下是不同类型资源冗余的情况及解决办法:
- 材质的冗余:主要是废弃掉的粒子效果仍然被打入到了 AB 中,删除这些粒子效果即可。
- 动画冗余:忘记将 UI 动画打到公共 AB 中,把动画目录添加到公共 AB 即可。
- Shader 冗余:每个材质被单独打到独立的 AB 中,导致材质使用的 Shader 被重复打入。这里存在一个误区,将 Shader 放到一个 Prefab 中,再将 Prefab 打入到公共 AB 中,并不能使这些材质 AB 依赖于这个公共 AB。在 Unity 5.x 中,AB 之间的依赖必须是显式的,而不能是隐式的,必须显式地将 Shader 的路径加入到公共 AB 中,才能使材质 AB 依赖于公共 AB。
- Font 冗余:错误地使用了一个旧的字体,解决办法是调整所有使用旧字体的 UI。
- Mesh 冗余:模型打 AB 的时候忘记处理导致,将其打入到公共 AB 中即可。
三、迭代优化与验证
发现这些冗余资源后,我们新增了一个公共 AB,将冗余资源全部打入其中。运行时,首先加载这个公共 AB 里面所有的资源。
最终的优化结果如下:
- 剩下两个 Sprite 是错误引用了 Unity 自己的资源,可调整相关 UI 去掉对应的引用。
- Texture2D 中,一个是上面错误的 Sprite 使用对应的纹理;一个是角色模型的材质中引用到的纹理,没有打入到公共 AB 中;还有三个比较特殊,这三个纹理对应的 Sprite 已经打入到公共 AB 中了,但是在 UI 中,是以 RawImage 的方式引用到这几个 Sprite。RawImage 引用的 Sprite 相当于直接引用纹理,而不是 sprite,导致不能使用公共 AB,修正方法是额外复制一份这些 sprite,设置其 importe typ 为 texture,将这些 Texture2D 打入到公共 AB 中。
可以看出,要完全优化掉这些冗余资源,还需要对现有的 UI 等做一些修改,所以 AB 优化不仅仅是优化打包流程。
四、额外的收获
1. Sprite 未打包成图集问题
通过查看每个 AB 中包含的资源,我们发现 Sprite 竟然都没有打包成 Sprite atlas,UI 纹理都是一张张碎图。原因主要有两点:一是 Sprite 没有设置 packingtag;二是 Sprite 都放在 Resources 目录下面,导致打包 AB 的时候,Resources 目录下的 Sprite 不会生成图集。因此,我们调整了打包代码,在打包的时候将这些 Sprite 移动到 resources 外面的某个目录中,打包 AB 结束后再放回去,之后 texture2d 的名字都变成了 spriteatlas。
2. 旧资源打包问题
我们还发现一些旧的 Sprite 被打包进了 AB 中。利用 UWA 工具,我们很容易就找到了所有引用到旧资源的 UI,然后在 Unity 中进行调整,去掉对旧资源的引用。
五、结合 Unity Profiler 优化内存的占用
虽然已经去除了 AB 的冗余,但优化工作并未结束。我们编译了一个 Development 的程序,并设置连接到 Profiler。在 Profiler 中查看内存的使用情况,发现纹理内存占用大大降低。之前为 50 - 60MB,优化后降至 20 - 30MB。接着进行一次内存采样,查看每个纹理的内存大小,发现有些图特别大,这是因为没有设置为压缩格式。在 iOS 平台应设置为 PVRTC 格式,在 Android 平台应设置为 ETC1 格式。设置为压缩格式后,虽然品质会有一些降低,但内存和加载速度会得到优化。
六、总结
总之,使用 UWA 的资源检测与分析工具,可以非常直观地看到所有的 AssetBundle 以及资源的状态,帮助我们进行更高效的资源分析和优化。