03-03-架构篇-Runtime加载系统架构
Runtime 端系统架构
篇章:03-架构篇
阅读时间:约 40 分钟
前置知识:了解 Editor 端系统架构
一、引言
本章将深入解析 YooAsset 的 Runtime 端系统架构。Runtime 端是 YooAsset 的运行层,在游戏运行时工作,负责资源的加载、管理、缓存和卸载。Runtime 端是玩家实际使用的部分,其架构设计的优劣直接影响游戏的性能和体验。
YooAsset 的 Runtime 端采用了 YooAssets → ResourcePackage → ResourceManager → Provider 的分层架构设计,职责清晰,分工明确。本章将详细解析 Runtime 端的各个核心模块。
二、YooAssets 静态入口
2.1 YooAssets 的概念
YooAssets 是 YooAsset 框架的全局静态入口,提供了统一的 API 让开发者与 YooAsset 进行交互。
YooAssets 的设计理念:
YooAssets 采用静态类设计,提供了全局唯一的入口点。开发者只需要调用 YooAssets 提供的静态方法就可以完成所有资源管理操作。
YooAssets 的特点:
- 静态入口:全局唯一的静态类,便于调用
- 统一 API:提供统一的 API 屏蔽内部实现
- 多 Package 支持:支持同时管理多个 ResourcePackage
YooAssets 的 API 设计:
public static class YooAssets
{
public static ResourcePackage CreatePackage(string packageName);
public static bool InitPackage(ResourcePackage package);
public static void DestroyPackage(ResourcePackage package);
public static ResourcePackage GetPackage(string packageName);
public static void SetDefaultPackage(ResourcePackage package);
public static ResourcePackage GetDefaultPackage();
}
2.2 YooAssets 的初始化流程
YooAssets 的初始化流程如下:
- 创建 YooAssets 设置:配置 YooAssetsSettings,包括文件服务器 URL、加密密钥等
- 创建 ResourcePackage:通过 YooAssets.CreatePackage 创建 ResourcePackage
- 初始化 ResourcePackage:通过 YooAssets.InitPackage 初始化 ResourcePackage
- 设置默认 Package:通过 YooAssets.SetDefaultPackage 设置默认 Package
- 开始使用资源:通过 ResourcePackage 加载资源
YooAssetsSettings 配置详解:
YooAssetsSettings 是 YooAssets 的全局配置,包括:
- 文件服务器 URL:用于资源下载的服务器地址
- 加密密钥:用于资源解密的密钥
- 备用 URL:备用文件服务器地址
- 超时设置:下载超时、连接超时等
- 重试策略:下载失败时的重试策略
初始化参数详解:
public class InitializeParameters
{
public string LocationToLower; // 地址转小写
public string ScreenOrientation; // 屏幕方向
public AssetBundleDecryptionServices AssetBundleDecryptionServices; // 解密服务
public IDeliveryQueryServices DeliveryQueryServices; // 远端查询服务
public IBuildinQueryServices BuildinQueryServices; // 内置查询服务
public IRemoteServices RemoteServices; // 远端服务
public ICacheSystem CacheSystem; // 缓存系统
}
2.3 多 Package 架构
YooAssets 支持同时管理多个 ResourcePackage:
多 Package 的使用场景:
- 游戏分包:将游戏分成多个 Package,便于热更新
- DLC 支持:支持 DLC 的独立加载和更新
- 模块化设计:支持游戏模块的独立加载
多 Package 的管理:
// 创建多个 Package
var packageA = YooAssets.CreatePackage("PackageA");
var packageB = YooAssets.CreatePackage("PackageB");
// 初始化 Package
YooAssets.InitPackage(packageA);
YooAssets.InitPackage(packageB);
// 切换默认 Package
YooAssets.SetDefaultPackage(packageA);
// 加载资源
packageA.LoadAssetAsync<GameObject>("prefab_a");
packageB.LoadAssetAsync<GameObject>("prefab_b");
多 Package 的实现:
YooAssets 内部维护了一个 Dictionary<string, ResourcePackage>,用于管理所有 Package。每个 Package 都有自己的 Manifest、FileSystem 和 ResourceManager。
三、ResourcePackage 资源包
3.1 ResourcePackage 的概念
ResourcePackage 是 YooAsset 资源管理的核心抽象,封装了一组相关资源的加载、卸载和管理。
ResourcePackage 的设计理念:
ResourcePackage 抽象了"一个完整的资源包"的概念,包括资源的加载、卸载、缓存、热更新等所有功能。
ResourcePackage 的特点:
- 封装性:封装了资源管理的所有细节
- 独立性:每个 Package 独立管理自己的资源
- 可配置性:Package 的配置可以独立修改
3.2 ResourcePackage 的组成
ResourcePackage 由以下核心组件组成:
ResourcePackage 组成
├── PackageManifest:包清单,记录所有 Bundle 的信息
├── FileSystem:文件系统,负责跨平台文件访问
├── ResourceManager:资源管理器,负责资源加载和缓存
├── DownloadManager:下载管理器,负责资源下载
├── CacheSystem:缓存系统,负责缓存管理
└── Provider Pool:Provider 池,缓存已创建的 Provider
PackageManifest 详解:
PackageManifest 是 ResourcePackage 的清单文件,包含了所有 Bundle 的信息。ResourcePackage 通过 PackageManifest 来定位资源。
FileSystem 详解:
FileSystem 是 ResourcePackage 的文件系统,负责跨平台文件访问。YooAsset 通过 IFileSystem 抽象层屏蔽了不同平台的差异。
ResourceManager 详解:
ResourceManager 是 ResourcePackage 的资源管理器,负责资源加载、缓存和引用计数管理。
DownloadManager 详解:
DownloadManager 是 ResourcePackage 的下载管理器,负责资源下载和热更新。
CacheSystem 详解:
CacheSystem 是 ResourcePackage 的缓存系统,负责缓存管理和过期清理。
Provider Pool 详解:
Provider Pool 是 ResourcePackage 的 Provider 池,缓存已创建的 Provider,避免重复创建。
3.3 ResourcePackage 的生命周期
ResourcePackage 的生命周期如下:
- 创建:通过 YooAssets.CreatePackage 创建 Package
- 初始化:通过 YooAssets.InitPackage 初始化 Package
- 加载资源:通过 Package.LoadAssetAsync 加载资源
- 热更新:通过 UpdatePackageManifestAsync 进行热更新
- 销毁:通过 YooAssets.DestroyPackage 销毁 Package
创建详解:
Package 的创建只是创建一个内存对象,初始化必要的字段(如 PackageName)。实际的资源加载会在初始化阶段进行。
初始化详解:
Package 的初始化会进行以下操作:
- 加载 PackageManifest 文件
- 初始化 FileSystem
- 初始化 ResourceManager
- 初始化 DownloadManager
- 初始化 CacheSystem
加载资源详解:
Package 提供了多种资源加载方式:
- LoadAssetAsync:异步加载资源
- LoadSceneAsync:异步加载场景
- LoadSubAssetsAsync:异步加载子资源
- LoadAllAssetsAsync:异步加载所有资源
热更新详解:
Package 的热更新流程:
- 请求服务器 Manifest
- 与本地 Manifest 对比
- 下载差异 Bundle
- 切换到新版本
销毁详解:
Package 的销毁会进行以下操作:
- 卸载所有已加载资源
- 清空 Provider Pool
- 关闭 FileSystem
- 释放内存资源
四、ResourceManager 架构
4.1 ResourceManager 的概念
ResourceManager 是 YooAsset 的资源管理器,负责资源加载、缓存、引用计数等核心功能。
ResourceManager 的设计目标:
ResourceManager 旨在提供高效、灵活、可靠的资源管理能力。它是 Runtime 层的核心模块。
ResourceManager 的职责:
- 资源加载:根据资源地址加载 AssetBundle 中的资源
- 资源缓存:管理已加载资源的内存缓存
- 引用计数:使用引用计数管理资源的引用关系
- 依赖管理:管理资源之间的依赖关系
- 资源释放:根据引用计数释放不再使用的资源
4.2 ResourceManager 的内部结构
ResourceManager 内部维护了多个重要的集合:
public class ResourceManager
{
// Provider 缓存
private Dictionary<string, ProviderBase> _providerCache;
// 加载中队列
private List<ProviderOperation> _loadingQueue;
// 加载完成列表
private List<ProviderOperation> _loadingCompleted;
// Bundle 加载器池
private Dictionary<string, BundleLoader> _bundleLoaders;
}
Provider 缓存详解:
Provider 缓存用于存储已创建的 Provider 对象。当请求加载某个资源时,ResourceManager 会先在 Provider 缓存中查找是否已存在对应的 Provider。
加载中队列详解:
加载中队列用于管理正在加载的 Provider。当多个请求同时加载同一资源时,ResourceManager 会复用同一个 Provider。
加载完成列表详解:
加载完成列表用于在每帧结束时检查加载完成的 Provider,并触发回调通知。
Bundle 加载器池详解:
Bundle 加载器池用于管理已加载的 AssetBundle。Bundle 加载器通过引用计数管理 Bundle 的生命周期。
4.3 资源加载流程
ResourceManager 的资源加载流程如下:
- 接收资源加载请求:通过 Package.LoadAssetAsync 发起请求
- 查找 Provider:在 Provider 缓存中查找是否已存在对应的 Provider
- 创建 Provider:如果不存在,创建新的 Provider
- 将请求加入 Provider:将加载请求加入 Provider 的等待队列
- Provider 执行加载:Provider 开始执行实际的加载操作
- 触发回调通知:加载完成后触发回调通知
查找 Provider 详解:
查找 Provider 时使用资源地址作为 Key。ResourceManager 会先在缓存中查找,如果存在则复用,否则创建新的 Provider。
创建 Provider 详解:
创建 Provider 时会根据资源类型创建对应类型的 Provider。常见的 Provider 类型包括:
- AssetProvider:普通资源 Provider
- SceneProvider:场景资源 Provider
- ComponentProvider:组件资源 Provider
- RawAssetProvider:原生资源 Provider
加载请求处理详解:
Provider 使用引用计数管理加载请求。每次 LoadAsync 调用会增加引用计数,每次 Release 调用会减少引用计数。当引用计数为 0 时,Provider 会自动销毁。
4.4 引用计数机制
引用计数是 YooAsset 资源管理的核心机制:
引用计数的概念:
引用计数记录了资源被引用的次数。每次资源被引用时,引用计数加 1;每次资源被释放时,引用计数减 1。当引用计数为 0 时,资源会被卸载。
引用计数的实现:
public abstract class ProviderOperation
{
public int RefCount; // 引用计数
public void Acquire()
{
RefCount++;
// 通知子依赖增加引用
}
public void Release()
{
RefCount--;
if (RefCount <= 0)
{
// 销毁资源
}
}
}
引用计数的应用:
引用计数用于管理资源生命周期。当多个对象引用同一资源时,资源不会因为某个对象释放而被错误卸载。
引用计数的优点:
- 避免内存泄漏:确保资源在不再使用时及时释放
- 避免重复加载:相同资源只加载一次
- 自动管理:自动管理资源的生命周期
引用计数的注意事项:
开发者必须严格遵守"Acquire-Release 配对"的原则,避免出现引用计数泄漏或重复释放。
五、Provider 体系
5.1 Provider 的概念
Provider 是 YooAsset 的资源提供者,封装了资源加载的具体逻辑。
Provider 的设计理念:
Provider 模式是 YooAsset 资源加载的核心设计模式。每个 Provider 对应一个资源,封装了资源的加载逻辑、状态管理和回调通知。
Provider 的特点:
- 单一职责:每个 Provider 只负责一个资源的加载
- 状态管理:Provider 维护了资源的加载状态
- 回调通知:Provider 支持加载完成、失败等的回调通知
- 引用计数:Provider 内置引用计数管理
5.2 Provider 类型
YooAsset 提供了多种 Provider 类型:
| Provider 类型 | 用途 | 特点 |
|---|---|---|
| AssetProvider | 普通资源 | 最常用的 Provider |
| SceneProvider | 场景资源 | 异步加载场景 |
| SubAssetsProvider | 子资源 | 加载包含多个资源的 AssetBundle 中的特定子资源 |
| RawAssetProvider | 原生资源 | 加载原生格式(图片、文本等) |
| BundleProvider | Bundle 资源 | 加载整个 AssetBundle |
AssetProvider 详解:
AssetProvider 是最常用的 Provider,用于加载普通资源(如 Prefab、Texture、Material 等)。它会加载包含资源的 AssetBundle,然后从 AssetBundle 中加载目标资源。
SceneProvider 详解:
SceneProvider 用于加载场景资源。它使用 Unity 的 SceneManager 进行异步场景加载,并管理场景的激活和卸载。
SubAssetsProvider 详解:
SubAssetsProvider 用于加载子资源。例如,一个 Sprite Atlas 包含多个 Sprite,可以使用 SubAssetsProvider 加载特定的 Sprite。
RawAssetProvider 详解:
RawAssetProvider 用于加载原生格式资源。它不会将资源转换为 Unity 对象,而是返回原始的字节数据。
5.3 Provider 的状态机
Provider 内部维护了一个状态机:
Provider 状态机
├── None:初始状态
├── Loading:加载中
├── Checking:检查中
├── Success:加载成功
├── Failed:加载失败
└── Destroyed:已销毁
状态流转详解:
Provider 的状态流转如下:
- None → Loading:开始加载
- Loading → Checking:加载完成,进入检查阶段
- Checking → Success:检查通过
- Checking → Failed:检查失败
- Success/Failed → Destroyed:资源被销毁
状态机的作用:
状态机确保 Provider 在正确的状态下执行正确的操作。例如,只有在 Loading 状态下才能处理加载进度更新,只有在 Success 状态下才能返回资源对象。
六、BundleLoader 体系
6.1 BundleLoader 的概念
BundleLoader 是 YooAsset 的 AssetBundle 加载器,负责加载和缓存 AssetBundle。
BundleLoader 的设计理念:
BundleLoader 抽象了 AssetBundle 的加载过程,提供了统一的接口。它管理 AssetBundle 的加载、缓存、引用计数和卸载。
BundleLoader 的特点:
- 统一接口:提供统一的接口屏蔽不同平台的差异
- 引用计数:使用引用计数管理 AssetBundle 的生命周期
- 缓存机制:缓存已加载的 AssetBundle,避免重复加载
- 异步加载:支持异步加载,避免阻塞主线程
6.2 BundleLoader 类型
YooAsset 提供了多种 BundleLoader 类型:
BundleLoader 类型
├── AssetBundleLoader:标准 AssetBundle 加载器
├── RawBundleLoader:原生 Bundle 加载器
├── DecryptedBundleLoader:解密 Bundle 加载器
└── EncryptedBundleLoader:加密 Bundle 加载器
AssetBundleLoader 详解:
AssetBundleLoader 是标准的 AssetBundle 加载器,使用 Unity 的 AssetBundle.LoadFromFile 或 AssetBundle.LoadFromMemory 加载 AssetBundle。
DecryptedBundleLoader 详解:
DecryptedBundleLoader 是解密 Bundle 加载器,用于加载已解密的 AssetBundle。它会先解密数据,然后从解密后的数据加载 AssetBundle。
6.3 BundleLoader 的工作流程
BundleLoader 的工作流程如下:
- 接收加载请求:接收 AssetBundle 加载请求
- 检查缓存:检查是否已加载该 AssetBundle
- 执行加载:如果没有缓存,执行实际的加载操作
- 缓存 AssetBundle:将加载完成的 AssetBundle 缓存
- 管理引用计数:管理 AssetBundle 的引用计数
- 释放 AssetBundle:引用计数为 0 时释放 AssetBundle
检查缓存详解:
BundleLoader 维护了一个 AssetBundle 缓存字典。检查缓存时使用 Bundle 的路径或名称作为 Key。
执行加载详解:
执行加载时使用 Unity 的 AssetBundle 加载 API。具体的加载方式取决于 Bundle 的类型和位置。
引用计数管理详解:
BundleLoader 使用引用计数管理 AssetBundle 的生命周期。每个资源依赖一个 AssetBundle,资源的引用计数变化会影响 AssetBundle 的引用计数。
七、总结
本章深入解析了 YooAsset Runtime 端的系统架构,包括:
- YooAssets 静态入口:全局统一的 API 入口
- ResourcePackage 资源包:封装了一组相关资源的加载和管理
- ResourceManager 资源管理器:负责资源加载、缓存和引用计数
- Provider 资源提供者:封装了资源加载的具体逻辑
- BundleLoader 体系:负责 AssetBundle 的加载和缓存
Runtime 端架构是 YooAsset 框架的核心,理解 Runtime 端架构是掌握 YooAsset 资源管理机制的关键。接下来的章节将分别深入解析文件系统、异步操作系统和资源下载器等核心组件。
上一篇:Editor 端系统架构
下一篇:文件系统架构(IFileSystem)

本章将深入解析 YooAsset 的 Runtime 端系统架构。Runtime 端是 YooAsset 的运行层,在游戏运行时工作,负责资源的加载、管理、缓存和卸载。Runtime 端是玩家实际使用的部分,其架构设计的优劣直接影响游戏的性能和体验。
浙公网安备 33010602011771号