先抛出个问题:
我们在谈论资源管理的时候,是在讨论什么?
整理了一下内容,大概就以下几点:
- 目录规划
- 内存控制
- 包体大小控制
- AB打包粒度
一、目录规划
在开始资源管理之前,先讲一下目录规划。
实际的Unity项目,一般都会有几种重要开发人员参与客户端工程的资源传递: 策划、服务器、客户端、美术。(当然也会有 QA参与工程的情况,比如有一些白盒测试,或者QA部门十分强大需要对客户端性能检测部分进行埋点的)。
我们的项目目前几种开发人员都参与了客户端工程的内容提交。
策划:业务相关配置表
服务器:协议(服务器统一提交,避免协议修改之后前后端协议不一致产生问题)
美术:2d原画、3d模型【模型、动作】、UI
这个是团队配合的游戏,不是一个人的战斗,所以要分配好权限,分权到个人,这样,出了问题才能迅速定位。
以下是我整理过的客户端目录的总览:
![768746e87a5e301fe2d2e14238f22a79.png](https://img-blog.csdnimg.cn/img_convert/768746e87a5e301fe2d2e14238f22a79.png)
主要介绍2个文件夹:Art和Data文件夹;其他文件夹就很字面的意思
①Art文件夹:
![db6f48fc0989a8d3d39be5ba8cb497ca.png](https://img-blog.csdnimg.cn/img_convert/db6f48fc0989a8d3d39be5ba8cb497ca.png)
- 存放的是美术的原件资源,也就是美术最基本的素材。
- 比如UI的切图,Icon的资源,模型Fbx文件,场景贴图,材质球等。并且根据不同的类型存放在不同的目录下面。
- 美术同学只有这个目录的写入权限(但是有整个工程的读取权限)。
②Data文件夹:
![1b9d22ca0517e8473c8dd3c57869d693.png](https://img-blog.csdnimg.cn/img_convert/1b9d22ca0517e8473c8dd3c57869d693.png)
- 这个文件夹存放的是游戏运行中需要动态加载的文件,各种预制
- 比如动态生成的特效、战斗使用的技能指示器、动态修改的道具图片、业务使用的预制界面。
- 这个文件夹主要是客户端程序在管理。
策划提交的表格,以lua文件,直接提交到Lua/game/Table文件夹下。策划同学只有这个目录的写入权限。
二、内存控制
![52e73611abe24a36f5c1557970a37265.png](https://img-blog.csdnimg.cn/img_convert/52e73611abe24a36f5c1557970a37265.png)
①对于需要常驻内存的Bundle文件
对于存放非Prefab资源(特别是纹理)的Bundle文件,可以考虑使用 WWW.LoadFromCacheOrDownload或AssetBundle.CreateFromFile加载
从而避免 WebStream常驻内存;优先考虑减小内存占用
而对于存放较多Prefab资源的Bundle,则考虑使用new WWW加载
因为这类Bundle用WWW.LoadFromCacheOrDownload加载时产生的SerializedFile可能会比new WWW产生的WebStream更大。
②对于加载完后即卸载的Bundle文件
分两种情况: 优先考虑速度(加载场景时)和 优先考虑流畅度(游戏进行时)。
1)加载场景的情况下,需要注意的是 避免WWW对象的逐个加载导致的CPU空闲,可以考虑使用加载速度较快的WWW.LoadFromCacheOrDownload或AssetBundle.CreateFromFile,但需要避免后续大量地进行Load资源的操作,引起IO开销(可以尝试直接 LoadAll)。
2) 游戏进行的情况下,则需要 避免使用同步操作引起卡顿,因此可以考虑使用new WWW配合 AssetBundle.LoadAsync来进行平滑的资源加载,但需要注意的是,对于Shader、较大的Texture等资源,其初始化操作通常很耗时,容易引起卡顿,因此建议将这类资源在加载场景时进行 预加载。
③只在Bundle需要加密的情况下,考虑使用CreateFromMemory
因为该接口加载速度较慢。
三、包体大小控制
- 删除无用资源(可以用AssetDatabase.FindAssets查找引用、AssetDatabase.GetDependencies获取路径)
- 压缩资源包(lzma、lz4压缩)
- 高清资源上传到cdn,使用时请求下载
四、AB打包粒度
关于AB的学习,之前有写了一些拙劣的学习文章:
- 【unity游戏开发】AB学习(一)—AB基础知识
- 【unity游戏开发】AB学习(二)—AB打包策略
- 【unity游戏开发】AB学习(三)—热更学习
- 【Unity游戏开发】Addressables学习与使用
只有控制好AB的颗粒度大小,才能保证更新的时候不会有大量的AB文件需要更新,尽量做到最小化更新文件。
划分Assetbundle的粒度主要考虑4个方面:资源类型、冗余大小、程序性能、后期维护。
在最终资源粒度划分成型前,大概经历了3个阶段,每个阶段所考虑的要素不同。
①探索阶段
在热更新模块设计初期就划分出合适的粒度是比较困难的,在这个阶段主要的目的是模块的实现,只需按照类型进行简单划分即可。资源的类型有: 音乐(音效)、配置文件、特效、Item、NPC、Monster、Role、UI、Scene、脚本(Lua)。
②优化阶段
以常见的MMORPG项目来说,这个阶段热更新模块已经通过了内部测试。但是在实际使用过程中,会发现部分Assetbundle过大,加载时间较长,出现了明显的卡顿,这时可以考虑拆分Monster、Role、Scene这3个焦点Assetbundle。
1. Monster的拆分标准是骨骼重定向,unity支持多个模型共用一套骨骼,从而 共享一套模型动画。使用这个机制会节省大量资源,按照这个原则,我们 把所有共享骨骼的模型放在一个Assetbundle里,这样既减小了IO的压力,又使冗余做到了最小。
2. Role的拆分同样遵循上述规则,同时由于role的武器是单独的模型(支持换装),也就是 一个类型的Role对应两个AssetBundle,Role本身+武器。
3. Scene的拆分比较简单,之前是所有的Scene一个Assetbundle,现在改为一种类型scene一个Assetbundle。
③测试阶段
此阶段主要对项目进行加载速度、IO占用、资源冗余来做整体测试,发现局部问题并针对性解决。
参考
Unity资源管理(一)
Unity文件、文件引用、Meta详解
AssetBundles和Resources指南【译】
Unity手游实战:从0开始SLG——Unity目录分布(Asset权限规划)