# 前言
在我们项目中,资源打包主要通过 AssetLable 的功能对需要打包的对象进行搜集:
按照指定规则设置资源的 AssetLable ,然后通过 AssetLable 再分类搜集资源,采用自定义容器管理资源引用,设置 AssetBundleName,最终出包。
在对代码走了一个流程后,将流程大概流程记一下,做做记录。
# 标签功能
- 在 Unity 搜索栏输入『l:Name』可以直接查找到所有指定标记的资源
例如: - 代码中通过 AssetDatabase.FindAssets 获取所有指定标签资源
例如通过该功能获取所有标签为 “Name” 的资源:
AssetDatabase.FindAssets("l:Name", new string[1] { "Assets/Resources" }); |
- 对指定资源的标签操作:
- AssetDatabase.GetLabels:获取
- AssetDatabase.SetLabels: 设置
- AssetDatabase.ClearLabels: 清除
# 流程
目前我们项目实际使用流程如下:
按照指定规则设置对应的 AssetLabel (可称为初始化资源环境,如果有设置过,该步骤其实可跳过)
获取所有打上标签资源
然后获取文件列表 (包括列表中每个资源对应的引用 [AssetDatabase.GetDependencies]),转化为自定义引用管理容器 (EditorAssetData) 存放,各种依赖信息
上述步骤每个资源都已通过 AssetDatabase.GetDependencies 获取到了自己的引用资源,这些生成的 EditorAssetData 目前统一存放于一个字典中,此时设置每个资源引用实际对应的 EditorAssetData 上下级依赖
注:这里 GetDependencies 获取后会剔除自身,因此相当于在这打断了下级资源造成的循环引用。
如下代码所示:循环所有搜集资源,首先将每个资源的所有下级 (即包括下级的下级) 引用加入自身,然后循环直接下级,将自身设置为下一级的父引用
EditorAssetData[] _array = dic.Values.ToArray();
for (int i = 0; i < _count; ++i)
{
EditorAssetData _info = _array[i];
int _listCount = _info.DownDependentPathList.Count;
for (int j = 0; j < _listCount; ++j)
{
string _downPath = _info.DownDependentPathList[j];
if (dic.ContainsKey(_downPath))
{
_info.AddDownDependence(dic[_downPath]);
}
}
_listCount = _info.NoRecursiveDownDependentPathList.Count;
for (int j = 0; j < _listCount; ++j)
{
string _downPath = _info.NoRecursiveDownDependentPathList[j];
if (dic.ContainsKey(_downPath))
{
dic[_downPath].AddUpDependence(_info);
}
}
}
所以,实际上我们项目加载一个资源,是会同时帮忙加载下一级,以及下级资源的引用的 (平级加载所有依赖)。
按照一定规则整理资源,如一个资源最顶级对其的引用 (递归上级资源)、上级依赖大于 1 的当做公共资源单独打包
重复名提示
在引用管理容器中命名逻辑上 AssetBundleName,并剔除无效资源 (如父级没有被引用)
- 指定了 IsBuildSingle 标签的,直接用自己的 AssetBundleName 单打
- 只有一个上级资源的,资源的 AssetBundleName 直接设置为上级资源同名 (与上级打一块)
使用所有需打包的文件列表生成 ManiFestText:这是所有资源的描述
使用所有需打包的文件列表生成 AssetBundleText:这是所有资源的数据
将 ManiFestText 与 AssetBundleText 合并为一个自定义的 ScriptableObject 描述对象,并创建对应 Prefab,设置 AssetBundleName
调用 Unity AssetImporter 接口将所有逻辑 AssetBundleName 进行实际资源设置
调用 BuildPipeline.BuildAssetBundles 接口,打包最终 AssetBundle 资源
后续实际加载流程同理,在 FResourcesManager 首先加载 ManiFestText、AssetBundleText 资源引用、描述数据,再次形成 打包时处理生成的 『引用管理结构』,然后再依次加载公共资源 (Shader、初始配置等),进入正式流程。
# 总结
整个流程理下来,可以看出,我们项目的资源管理,完全是自己实现的一套:包括打包、加载、引用管理等。
除了打包时调用 UnityEditor 接口获取某资源的引用外,都采用了一套自定义资源管理流程封装,没有使用 Unity 内置接口如 AssetBundleManifest 等。
所以对于我们项目,打包资源时与 assetbundle 同步生成的 『.manifest』其实可以直接删掉,包括热更也是没用的,数据都是统一存在我们自定义结构中了。