资源构建

指定资源目录

CatAsset基于资源目录构建规则以进行批量资源构建,所以构建资源的第一步便是指定资源目录

操作方法为:右键目录-添加为资源包构建目录

点击上方工具栏CatAsset-打开资源包构建窗口

点击构建目录页签,即可看到此目录的信息

选择构建规则

构建规则决定了此目录下所有资源文件会按照什么样的方式去构建成为资源包

点击NAssetToOneBundle处的下拉按钮展开下拉列表,选择构建规则

CatAsset默认提供了5种构建规则

  1. NAssetToNBundle(将指定目录下所有资源分别构建为一个资源包)
  2. NAssetToNRawBundle(将指定目录下所有资源分别构建为一个原生资源包)
  3. NAssetToOneBundle(将指定目录下所有资源构建为一个资源包)
  4. SecondDirectoryBasedNAssetToOneBundle(将指定目录下所有二级子目录各自使用NAssetToOneBundle规则进行构建)
  5. TopDirectoryBasedNAssetToOneBundle(将指定目录下所有一级子目录各自使用NAssetToOneBundle规则进行构建)

如何扩展构建规则?

只需要通过自定义类实现IBundleBuildRule接口即可

为什么没有NAssetToOneRawBundle?

因为原生资源不使用AssetBundle进行构建,原生资源包只是被虚拟出来方便进行统一管理的,实际上并不存在对应的资源包文件,所以也不存在一个原生资源包内有多个原生资源的情况,对于原生资源而言,资源文件即是资源包文件

Filter

此处等价于在搜索栏输入的filter,如t:prefab表示此资源目录只会构建预制体资源

正则筛选

在正则一栏中输入正则表达式,即可仅将资源路径(以Assets/开头)匹配此表达式的资源纳入构建范围内

资源组

资源组设置用于可更新模式下更新资源,组名相同的资源目录所构建的资源包会被视为同一个资源组,单机模式下可忽略此项设置

压缩设置

此处用于设置此资源目录所构建的AssetBundle的压缩格式

加密设置

此处用于设置此资源目录所构建的AssetBundle的加密方式

注意:WebGL平台下不会对资源进行加密,所以此设置无效

预览资源包

切换分页到资源包预览,点击刷新即可预览到构建后的资源包的内容

BundleRes/Chapter1.bundle部分即是此资源包在构建后的,相对于只读区/读写区的路径

资源数表示此资源包内的资源数量

预估长度表示此资源包内的资源文件长度总和(因此并不表示此资源包在构建后的文件长度,因为在进行预览时并未实际构建出此资源包)

预览资源

点击资源包预览条目左侧的三角形,即可展开资源列表,查看资源相关信息

Assets/BundleRes/Chapter1/B1.prefab为此资源的加载路径

循环依赖检测

点击检测资源循环依赖检测资源包循环依赖即可在编辑器下检查相关循环依赖问题

准确预估贴图大小选项若勾选即会按照贴图资源受压缩特使影响的实际大小进行预估长度,但在贴图资源数量多时会拖慢刷新速度

冗余分析

CatAsset会自动将冗余资源按照其关联划分为多个冗余资源包

设定构建配置

在预览完成后,切换分页到构建配置,可进行相关设置

构建设置

构建设置分为3种:

  1. WriteLinkXML:会通过SBP在资源包构建完成后自动生成link.xml文件到输出目录
  2. ForceRebuild:强制全量构建
  3. AppendMD5:在资源包名上附加MD5值

资源包全局压缩设置与资源包全局加密设置

这两处设置分别用于决定全局的压缩与加密设置,此外每个资源目录还可决定自身独立的压缩与加密设置

注意:原生资源的压缩设置无效

最终输出目录

资源包在构建完成后的最终输出目录为:资源包构建输出根目录/资源包构建平台/资源清单版本号/,如Library/AssetBundlesOutput/StandaloneWindows/1

资源清单CatAssetManifest.json和CatAssetManifest.data也会被写入到此目录下

构建补丁资源包

当勾选构建补丁资源包时,CatAsset会自行检查发生了变化的资源及其相关资源,然后将这些资源进行单独构建以此提升构建资源包的速度,新的补丁资源包会以原资源包名附加_patch后缀的形式存在,一个正式资源包只会有一个对应的补丁资源包

第一次需要先完整构建资源包生成缓存文件后,才能进行构建补丁资源包

由于补丁资源是通过与上一次完整构建的缓存进行对比计算出的,所以随着变化的资源增多,构建补丁资源的速度也会逐渐接近构建完整资源包的速度,此时就需要重新进行一次完整构建

当一个资源包里的所有资源都发生了变化时,构建出的补丁资源包就会转为正式资源包以完全替换旧的资源包,此时将不再具有_patch后缀

资源的加载与卸载

运行前的准备

在运行前,需要先将CatAssetComponent挂载至游戏物体上

或者通过项目中自定义的Manager来进行CatAssetManager.Update的调用

运行模式

CatAsset提供了2种运行模式

  • PackageOnly(单机模式,仅使用安装包内的资源)
  • Updatable(可更新模式)

后续将以单机模式为例

资源清单检查

单机模式下,在加载资源前需要先进行资源清单检查,才能正确初始化CatAssetManager

1
CatAssetManager.CheckVersion(OnVersionChecked onVersionChecked)

回调以VersionCheckResult为参数,包含了是否检查成功的信息

编辑器资源模式

若勾选编辑器资源模式,即可在不进行资源包构建的前提下快速运行游戏,此时CheckVersion会直接返回

资源类别

CatAsset支持3种类别的资源:

  1. 内置资源包资源(在Unity工程中使用CatAsset构建,从AssetBundle中加载的资源,如Prefab、Scene文件等)
  2. 内置原生资源(在Unity工程中使用CatAsset构建,不基于AssetBundle而是直接加载其二进制数据的资源,如DLL、Lua文件等)
  3. 外置原生资源(不使用CatAsset构建,直接从读写区加载其二进制数据的资源,如玩家自定义的图片、文本等)

导入外部的资源包

可通过将读写区的外部资源包导入CatAssetManager,以将其视为内置资源包资源加载(这些被导入的资源包必须是通过CatAsset构建出来的,这样才有清单文件),接口为:

1
CatAssetManager.ImportInternalAsset(string manifestPath,Action<bool> callback,string bundleRelativePathPrefix = null)

manifestPath为要导入的资源包的资源清单相对于读写区的路径

callback为导入完毕的回调

bundleRelativePathPrefix为资源包相对于读写区路径的额外前缀,若为null,则加载资源包时的路径为Application.persistentDataPath/bundleRelativePath,否则为Application.persistentDataPath/bundleRelativePathPrefix/bundleRelativePath,此参数主要用于方便自定义需要导入的资源包的位置

此功能主要用于实现AssetBundle类型的Mod文件加载功能

加载资源

在资源清单检查完毕后即可进行资源的加载(所有加载都是异步的

3类资源(非场景)统一通过以下接口进行加载:

1
AssetHandler<T> handler = CatAssetManager.LoadAssetAsync<T>(string assetName, CancellationToken token = default,TaskPriority priority = TaskPriority.Low)

assetName为资源的加载路径,若资源类别为1和2,则是一个**Assets/**开头的路径,若为3,则是1个相对于读写区的路径

token用于进行加载的取消操作

priority表示此加载任务的优先级

资源句柄

调用加载资源的接口后会返回一个表示资源句柄的AssetHandler<T>对象,其封装了对被加载的资源的相关操作,如注册此资源加载结束回调,await handler以等待加载结束,资源是否加载成功以及最重要的获取被加载的资源、卸载句柄等

可通过注册handler.OnLoaded回调或直接await handler等待加载完成,然后通过handler.Success判断是否加载成功,handler.Asset获取到加载到的资源,或是通过handler.Unload()卸载句柄

1
2
3
4
5
6
7
8
9
10
CatAssetManager.LoadAssetAsync<TextAsset>("Assets/BundleRes/RawText/rawText1.txt").OnLoaded +=
handler =>
{
if (handler.IsSuccess)
{
Debug.Log($"加载原生资源 文本文件:{handler.Asset.text}");
}

handler.Unload();
};
1
2
3
4
5
6
AssetHandler<TextAsset> handler = await CatAssetManager.LoadAssetAsync<TextAsset>("Assets/BundleRes/RawText/rawText1.txt");
if (handler.IsSuccess)
{
Debug.Log($"加载原生资源 文本文件:{handler.Asset.text}");
}
handler.Unload();

句柄中对资源对象的处理

AssetHandler<T>封装了资源加载结果,包括原始资源实例资源类别和用于获取资源的AssetObj,AssetAssetAs<T>

AssetObj表示原始资源实例

Asset表示AssetObj通过AssetAs<T>转换后的结果

AssetAs<T>会根据传入的T类型以及资源类别来判断应该返回什么

其判断规则如下:

  1. Tobject类型时会直接返回原始资源实例
  2. 当资源类别为原生资源时,如果Tbyte[]类型,会直接返回原始资源实例,否则调用转换器将原始资源实例转换为对应类型的资源并返回
  3. 当资源类别为资源包资源时,如果TUnityEngine.Object及其派生类型,会直接返回原始资源实例,否则会报错

通常来说直接使用handler.Asset即可

原生资源的加载

对于原生资源而言,底层只能加载到byte[]数据

而为了能够进行统一的加载接口调用,需要将byte[]转换为调用加载接口时指定的类型

如何进行转换则是由自定义原生资源转换器CustomRawAssetConverter决定

CatAsset默认提供了3种类型的转换器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
static CatAssetManager()
{
RegisterCustomRawAssetConverter(typeof(Texture2D),(bytes =>
{
Texture2D texture2D = new Texture2D(0, 0);
texture2D.LoadImage(bytes);
return texture2D;
}));

RegisterCustomRawAssetConverter(typeof(Sprite),(bytes =>
{
Texture2D texture2D = new Texture2D(0, 0);
texture2D.LoadImage(bytes);
Sprite sp = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), Vector2.zero);
return sp;
}));

RegisterCustomRawAssetConverter(typeof(TextAsset),(bytes =>
{
string text = Encoding.UTF8.GetString(bytes);
TextAsset textAsset = new TextAsset(text);
return textAsset;
}));

}

若要注册自定义的转换器,需要调用

1
CatAssetManager.RegisterCustomRawAssetConverter(Type type, CustomRawAssetConverter converter)

批量资源加载

CatAsset支持对一组资源进行批量加载的操作,其接口为:

1
BatchAssetHandler handler = CatAssetManager.BatchLoadAssetAsync(List<string> assetNames,CancellationToken token = default, TaskPriority priority = TaskPriority.Low)

支持对3种类别资源的混合批量加载

注意:由于在编辑器资源模式下,对原生资源的加载必须显式指定加载类型为byte[],否则会被判断为内置资源包资源,而批量加载接口无法显式指定加载类型,所以无法在编辑器资源模式下对原生资源进行批量加载操作

资源卸载

CatAsset采用基于引用计数的资源卸载方式,因此在加载资源后需要有与其成对调用的卸载调用才能正确将资源卸载掉,卸载接口为:

1
CatAssetManager.UnloadAsset(AssetHandler handler)

1
assethandler.Unload()

可通过BatchAssetHandler.Unload来进行对批量加载到的资源的统一卸载

可通过CatAssetManager.UnloadUnusedAssets来立即卸载所有引用计数为0且可卸载的资源以及没有资源在使用中的资源包

卸载句柄

通过handler.Unload()会进行对句柄的卸载,其中会根据句柄当前状态进行处理:

  1. 若当前句柄无效,则不做处理
  2. 若当前资源加载中,则取消加载
  3. 若当前资源加载成功,则进行对资源的卸载
  4. 若当前资源加载失败,则仅释放句柄

场景管理

对于场景的加载与卸载使用与非场景资源不同的接口,分别为:

1
SceneHandler handler = CatAssetManager.LoadSceneAsync(string sceneName,CancellationToken token = default, TaskPriority priority = TaskPriority.Low)
1
CatAssetManager.UnloadScene(SceneHandler scene)
1
sceneHandler.Unload()

资源生命周期绑定

考虑到手动调用卸载可能产生的不便性与易错漏性,可通过资源绑定接口将资源的生命周期与游戏物体/场景的生命周期进行绑定以实现自动卸载

绑定后会在游戏物体销毁时/场景卸载时自动对被绑定的资源句柄调用卸载接口

资源生命周期绑定接口为:

1
2
CatAssetManager.BindToGameObject(GameObject target, IBindableHandler handler)
CatAssetManager.BindToScene(Scene scene, IBindableHandler handler)

1
2
3
4
5
scene.BindTo(handler)
gameobject.BindTo(handler)

handler.BindTo(scene)
handler.BindTo(gameObject)

资源更新

在运行模式为可更新模式时可以进行资源更新的操作

设置资源更新Uri前缀

要进行资源更新,首先需要主动设置CatAssetManager.UpdateUriPrefix

下载资源文件时会以 UpdateUriPrefix/BundleRelativePath 为下载地址

检查资源版本

进行资源更新前,需要调用检查资源版本的接口

1
CatAssetManager.CheckVersion(OnVersionChecked onVersionChecked)

获取更新器信息

在资源版本检查完毕后,CatAsset会创建出需要进行更新的资源组所对应的更新器

此时可以通过CheckVersion传递给回调的VersionCheckResultGroupUpdaters字段获取到所有需要更新资源的更新器

或者通过遍历资源组信息列表,获取其对应的更新器来判断其是否有需要更新的资源

1
2
3
4
5
6
7
8
9
10
11
//遍历所有资源组的更新器
List<GroupInfo> groups = CatAssetManager.GetAllGroupInfo();
foreach (GroupInfo groupInfo in groups)
{
GroupUpdater updater = CatAssetManager.GetGroupUpdater(groupInfo.GroupName);
if (updater != null)
{
//存在资源组对应的更新器 就说明此资源组有需要更新的资源
Debug.Log($"{groupInfo.GroupName}组的资源需要更新");
}
}

在资源组的所有待更新资源都成功更新完毕后,会删除此资源组对应的更新器

更新资源组

使用更新资源组接口即可开始调用指定资源组的更新器,开始更新资源:

1
CatAssetManager.UpdateGroup(string group, BundleUpdatedCallback callback)

BundleUpdatedCallback为资源包更新回调,每次更新完毕一个资源包后都会调用此回调,其定义如下:

1
public delegate void BundleUpdatedCallback(BundleUpdateResult result);

BundleUpdateResult表示资源包更新结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/// <summary>
/// 资源包更新结果
/// </summary>
public readonly struct BundleUpdateResult
{
/// <summary>
/// 是否更新成功
/// </summary>
public readonly bool Success;

/// <summary>
/// 资源包更新器信息
/// </summary>
public readonly UpdateInfo UpdateInfo;

/// <summary>
/// 此资源包的资源组更新器
/// </summary>
public readonly GroupUpdater Updater;

//省略...
}

可从BundleUpdateResult中获取到GroupUpdater,以取得更详细的信息,如资源组名、需要更新的资源包数量/长度、已更新的资源包数量/长度

暂停/恢复更新

可通过相关接口暂停/恢复指定资源组更新器的资源更新行为:

1
2
CatAssetManager.PauseGroupUpdater(string group)
CatAssetManager.ResumeGroupUpdater(string group)

调试分析器

为了方便进行资源框架相关的调试,CatAsset提供了用于展示运行时信息的调试分析器窗口,点击上方工具栏CatAsset/打开调试分析器窗口即可打开

调试分析器可用于进行真机调试,只需要在构建安装包时勾选developmentBuildAutoconnect Profiler即可

通用说明

通过点击采样按钮,即可获取当前帧的分析器信息

通过滑动Slider或直接输入帧号,可切换到不同帧对应的分析器信息

资源包信息

资源包信息窗口提供了尚在内存中的资源包的相关信息

文件长度

其中资源包信息条目的文件长度表示资源包文件的实际长度,资源信息条目的长度表示此资源的原始文件长度

只显示主动加载的资源

主动加载:在业务层通过加载接口进行资源加载的行为

依赖加载:框架层自身通过依赖加载进行资源加载的行为

若勾选只显示主动加载的资源,则会将通过自动依赖加载出的资源的相关信息隐藏,使得开发者能够更专注于那些被主动加载的资源信息

引用计数

引用计数由主动加载的计数和依赖加载的计数2部分组成

引用计数的增减规则:

  1. 每一次对资源的主动加载或主动卸载会+1或-1此资源的引用计数
  2. 当资源的引用计数从0增加到1或从1减少为0时,会+1或-1直接依赖资源的引用计数(也就是说1个资源最多只会对它的所有直接依赖资源贡献1个引用计数

上游与下游

在依赖链中,若A依赖B,B依赖C,则称

C是B的上游节点,B是A的上游节点

A是B的下游节点,B是C的下游节点

通过点击查看依赖关系图按钮,即可查看与当前资源包/资源有直接/间接上下游关系的依赖关系图

引用计数 - 下游节点的数量 = 此资源被主动加载的次数

资源信息

资源信息窗口提供了尚在内存中的资源的相关信息,各列含义大致与资源包信息窗口的一致

任务信息

在CatAsset中,如加载、卸载、更新等异步操作都是由内置的任务系统实现的,可通过任务信息窗口查看当前进行中的任务

资源组信息

此窗口显示与资源组相关的信息

更新器信息

此窗口显示资源更新相关的信息