通用异步体系(OperationSystem)
篇章 :03-架构篇 阅读时间 :约 35 分钟 前置知识:了解 Runtime 端系统架构
一、引言
本章将深入解析 YooAsset 的通用异步体系(OperationSystem)。OperationSystem 是 YooAsset 异步操作管理的核心,它通过统一的抽象和调度机制,实现了高效、灵活的异步操作管理。
YooAsset 的 OperationSystem 是一个独立的子系统,被广泛用于资源加载、下载、解密、缓存等场景。本章将详细解析 OperationSystem 的设计和实现。
二、OperationSystem 的概念
2.1 为什么需要 OperationSystem
在 Unity 中,异步操作是一个常见的需求。常见的异步操作包括:
- 资源加载(LoadAssetAsync)
- 场景加载(LoadSceneAsync)
- 资源下载(DownloadAsync)
- 文件读取(ReadFileAsync)
传统异步操作的挑战:
在传统的异步操作实现中,开发者需要处理以下问题:
- 进度跟踪:如何跟踪异步操作的进度
- 状态管理:如何管理异步操作的状态
- 回调通知:如何在异步操作完成时通知调用者
- 优先级管理:如何管理异步操作的优先级
- 错误处理:如何处理异步操作中的错误
OperationSystem 的解决方案:
OperationSystem 通过统一的抽象和调度机制,提供了以下能力:
- 统一的异步操作接口
- 自动的进度跟踪
- 自动的状态管理
- 自动的回调通知
- 灵活的优先级管理
- 完善的错误处理
2.2 OperationSystem 的设计目标
OperationSystem 的设计目标如下:
统一性:
提供统一的异步操作接口,使所有异步操作都遵循相同的模式。
灵活性:
支持多种异步操作类型,可以灵活扩展新的异步操作。
可调度性:
支持异步操作的调度管理,可以控制异步操作的执行顺序和并发数。
可监控性:
支持异步操作的进度跟踪和状态查询。
2.3 OperationSystem 的组成
OperationSystem 由以下核心组件组成:
markdown
OperationSystem 组成
├── Operation(异步操作)
│ ├── AsyncOperationBase(基类)
│ └── 具体操作实现
├── OperationSystem(调度器)
│ ├── 优先级队列
│ ├── 时间片管理
│ └── 操作执行
├── OperationUpdater(更新器)
│ └── 帧更新逻辑
└── OperationHandle(操作句柄)
└── 对外接口
Operation 详解:
Operation 是异步操作的抽象,定义了异步操作的基本行为。具体的异步操作继承自 Operation,实现具体的逻辑。
OperationSystem 详解:
OperationSystem 是异步操作的调度器,负责管理所有异步操作的执行。
OperationUpdater 详解:
OperationUpdater 是异步操作的更新器,负责在每帧更新异步操作的状态。
OperationHandle 详解:
OperationHandle 是异步操作的句柄,对外暴露异步操作的接口。开发者通过 OperationHandle 与异步操作交互。
三、AsyncOperationBase 基类
3.1 AsyncOperationBase 的设计
AsyncOperationBase 是所有异步操作的基类,定义了异步操作的基本行为。
AsyncOperationBase 的属性:
csharp
public abstract class AsyncOperationBase
{
public EAsyncOperationStatus Status { get; protected set; }
public float Progress { get; protected set; }
public string Error { get; protected set; }
public bool IsDone => Status != EAsyncOperationStatus.None;
public event Action<AsyncOperationBase> OnCompleted;
public abstract void Start();
public abstract void Update();
public abstract void Destroy();
}
Status 属性详解:
Status 表示异步操作的当前状态,包括 None、Running、Succeed、Failed 四个状态。
Progress 属性详解:
Progress 表示异步操作的进度,范围 0-1。
Error 属性详解:
Error 表示异步操作失败时的错误信息。
OnCompleted 事件详解:
OnCompleted 是异步操作完成时触发的事件,可以通过订阅该事件来获取完成通知。
3.2 异步操作的状态机
异步操作内部维护了一个状态机:
sql
异步操作状态机
├── None:初始状态,操作尚未开始
├── Running:操作正在执行
├── Succeed:操作执行成功
└── Failed:操作执行失败
状态流转详解:
异步操作的状态流转如下:
- None → Running:调用 Start 方法后
- Running → Succeed:操作执行成功
- Running → Failed:操作执行失败
- Succeed/Failed → 销毁:调用 Destroy 方法
状态机的作用:
状态机确保异步操作在正确的状态下执行正确的操作,避免出现状态不一致的问题。
3.3 异步操作的生命周期
异步操作的生命周期如下:
- 创建:创建异步操作实例
- 启动:调用 Start 方法启动操作
- 更新:每帧调用 Update 方法更新操作状态
- 完成:操作完成后触发 OnCompleted 事件
- 销毁:调用 Destroy 方法销毁操作
创建详解:
创建异步操作实例时,会设置初始状态为 None,并初始化必要的字段。
启动详解:
调用 Start 方法启动异步操作。Start 方法会进行一些初始化工作(如加载资源、发送请求等),然后将状态设置为 Running。
更新详解:
每帧调用 Update 方法更新异步操作的状态。Update 方法会检查操作是否完成,并更新进度。
完成详解:
异步操作完成后,会将状态设置为 Succeed 或 Failed,并触发 OnCompleted 事件。
销毁详解:
调用 Destroy 方法销毁异步操作。Destroy 方法会清理异步操作占用的资源,如取消请求、释放内存等。
四、OperationSystem 调度器
4.1 OperationSystem 的工作原理
OperationSystem 是异步操作的调度器,负责管理所有异步操作的执行。
OperationSystem 的工作流程:
markdown
OperationSystem 工作流程
1. 接收异步操作(通过 ProcessOperaiton 方法)
2. 将异步操作加入优先级队列
3. 每帧更新时:
a. 按优先级处理队列中的操作
b. 调用每个操作的 Update 方法
c. 检查操作是否完成
d. 完成的操作触发回调
4. 销毁完成的操作
4.2 优先级队列
OperationSystem 使用优先级队列管理异步操作:
优先级定义:
YooAsset 定义了多个优先级:
- Low:低优先级
- BelowNormal:低于正常
- Normal:正常
- AboveNormal:高于正常
- High:高优先级
- Ultra:超高优先级
优先级的作用:
优先级决定了异步操作的执行顺序。高优先级的操作会优先执行,适用于需要紧急处理的操作。
优先级的应用:
- 资源加载:高优先级用于关键资源加载
- 资源下载:低优先级用于后台资源下载
- 缓存清理:低优先级用于后台缓存清理
4.3 时间片管理
OperationSystem 支持时间片管理,避免单帧执行过多异步操作:
时间片详解:
时间片是 OperationSystem 在单帧内可以执行异步操作的最大时间。超过时间片的操作会推迟到下一帧执行。
时间片的作用:
- 避免阻塞主线程
- 保证游戏帧率
- 平滑处理大量异步操作
时间片配置:
csharp
public class OperationSystem
{
public float TimeSlice { get; set; } = 0.5f; // 默认 0.5 毫秒
}
4.4 OperationSystem 的实现
OperationSystem 的核心实现:
csharp
public class OperationSystem
{
private List<AsyncOperationBase> _operations;
private List<AsyncOperationBase> _completeList;
private List<AsyncOperationBase> _destroyList;
public void ProcessOperaiton(AsyncOperationBase operation)
{
operation.Start();
_operations.Add(operation);
}
public void Update()
{
// 更新所有操作
float startTime = Time.realtimeSinceStartup;
for (int i = 0; i < _operations.Count; i++)
{
_operations[i].Update();
// 检查时间片
if (Time.realtimeSinceStartup - startTime > TimeSlice)
break;
}
// 处理完成的操作
ProcessCompleted();
}
}
五、OperationUpdater 更新器
5.1 OperationUpdater 的概念
OperationUpdater 是异步操作的更新器,负责在每帧更新异步操作的状态。
OperationUpdater 的设计:
OperationUpdater 是一个 MonoBehaviour,在 Unity 引擎的 Update 生命周期中调用 OperationSystem 的 Update 方法。
OperationUpdater 的实现:
csharp
public class OperationUpdater : MonoBehaviour
{
private void Update()
{
OperationSystem.Update();
}
}
5.2 OperationUpdater 的初始化
OperationUpdater 在 YooAsset 初始化时创建:
csharp
public class YooAssetsInitializer
{
public static void Initialize()
{
// 创建 OperationUpdater GameObject
GameObject updaterGo = new GameObject("OperationUpdater");
GameObject.DontDestroyOnLoad(updaterGo);
updaterGo.AddComponent<OperationUpdater>();
}
}
5.3 OperationUpdater 的注意事项
DontDestroyOnLoad:
OperationUpdater 使用 DontDestroyOnLoad 确保在场景切换时不被销毁。
Update 顺序:
OperationUpdater 的 Update 在所有业务脚本的 Update 之后执行,确保业务脚本能获取到最新的异步操作状态。
六、OperationHandle 句柄
6.1 OperationHandle 的概念
OperationHandle 是异步操作的句柄,对外暴露异步操作的接口。
OperationHandle 的设计:
OperationHandle 是对 AsyncOperationBase 的包装,提供了更友好的 API。
OperationHandle 的实现:
csharp
public class OperationHandle<T> where T : AsyncOperationBase
{
private T _operation;
public bool IsValid => _operation != null;
public bool IsDone => _operation?.IsDone ?? false;
public float Progress => _operation?.Progress ?? 0;
public string Error => _operation?.Error;
public T Operation => _operation;
public event Action<OperationHandle<T>> OnCompleted;
public void Release()
{
// 释放句柄
}
}
6.2 OperationHandle 的使用
开发者使用 OperationHandle 与异步操作交互:
csharp
// 发起异步操作
var handle = package.LoadAssetAsync<GameObject>("prefab_path");
// 注册完成回调
handle.OnCompleted += (op) => {
if (op.Error == null)
{
GameObject prefab = op.Asset;
// 使用资源
}
};
// 等待完成
await handle.Task;
// 释放句柄
handle.Release();
6.3 OperationHandle 的引用计数
OperationHandle 使用引用计数管理生命周期:
引用计数的作用:
引用计数确保异步操作在所有引用都释放后才被销毁。
引用计数的方法:
AddRef():增加引用计数Release():减少引用计数(引用计数为 0 时销毁)
七、异步操作类型
7.1 常见的异步操作类型
YooAsset 提供了多种异步操作类型:
资源加载操作:
csharp
public class AssetProvider : ProviderOperation
{
// 资源加载的具体实现
}
场景加载操作:
csharp
public class SceneProvider : ProviderOperation
{
// 场景加载的具体实现
}
下载操作:
csharp
public class DownloadOperation : AsyncOperationBase
{
// 资源下载的具体实现
}
解密操作:
csharp
public class DecryptOperation : AsyncOperationBase
{
// 资源解密的具体实现
}
Web 请求操作:
csharp
public class WebRequestOperation : AsyncOperationBase
{
// Web 请求的具体实现
}
7.2 自定义异步操作
开发者可以自定义异步操作,扩展 YooAsset 的功能:
自定义异步操作的步骤:
- 继承 AsyncOperationBase
- 实现 Start、Update、Destroy 方法
- 在合适的时机调用 Completed() 方法触发完成回调
自定义异步操作示例:
csharp
public class CustomAsyncOperation : AsyncOperationBase
{
public object Result { get; private set; }
public override void Start()
{
Status = EAsyncOperationStatus.Running;
// 启动自定义逻辑
}
public override void Update()
{
// 更新自定义逻辑
if (/* 完成条件 */)
{
Result = /* 实际结果 */;
Status = EAsyncOperationStatus.Succeed;
}
}
public override void Destroy()
{
// 清理资源
}
}
八、总结
本章深入解析了 YooAsset 通用异步体系(OperationSystem),包括:
- OperationSystem 的概念:统一的异步操作管理
- AsyncOperationBase 基类:异步操作的基础抽象
- OperationSystem 调度器:异步操作的调度管理
- OperationUpdater 更新器:异步操作的帧更新
- OperationHandle 句柄:对外暴露的异步操作接口
- 异步操作类型:常见和自定义的异步操作
OperationSystem 是 YooAsset 异步操作管理的核心,它通过统一的抽象和调度机制,为 YooAsset 的所有异步操作提供了高效、灵活、可靠的运行环境。
上一篇 :文件系统架构(IFileSystem) 下一篇 :资源下载器架构