源码-异步体系(OperationSystem)
篇章 :05-源码深度-运行时核心模块 阅读时间 :约 30 分钟 前置知识:了解 Provider 体系
一、引言
本章将深入解析 YooAsset 异步体系(OperationSystem)的源码实现。OperationSystem 是 YooAsset 异步操作管理的核心,提供了统一的异步操作管理接口。YooAsset 的所有异步操作都基于 OperationSystem 实现。
OperationSystem 的设计目标是提供统一、灵活、高效的异步操作管理能力。本章将从源码层面深入解析 OperationSystem 的设计和实现。
二、Operation 概述
2.1 Operation 的概念
Operation 是 YooAsset 异步操作的抽象:
Operation 的定义:
Operation 是一个抽象类,定义了异步操作的基本行为。
Operation 的特点:
- 统一接口:所有异步操作都遵循相同的接口
- 状态管理:Operation 维护自己的状态
- 进度跟踪:Operation 提供进度跟踪
- 回调通知:Operation 支持完成回调
Operation 的作用:
- 封装异步操作逻辑
- 提供统一的异步操作接口
- 支持异步操作的优先级调度
- 支持异步操作的时间片管理
2.2 Operation 状态机
Operation 内部维护了一个状态机:
sql
Operation 状态机
├── Pending:等待中
├── Running:运行中
├── Succeeded:成功
├── Failed:失败
└── Cancelled:已取消
Pending 详解:
Pending 是 Operation 的初始状态,Operation 创建后即进入 Pending 状态。
Running 详解:
Running 是 Operation 的运行中状态。Operation 被调度执行时进入 Running 状态。
Succeeded 详解:
Succeeded 是 Operation 的成功状态。异步操作执行成功时进入此状态。
Failed 详解:
Failed 是 Operation 的失败状态。异步操作执行失败时进入此状态。
Cancelled 详解:
Cancelled 是 Operation 的已取消状态。Operation 被取消时进入此状态。
2.3 Operation 状态详解
csharp
public enum EOperationStatus
{
None = 0,
Pending = 1,
Running = 2,
Succeeded = 3,
Failed = 4,
Cancelled = 5,
}
状态转换详解:
- None → Pending:Operation 被注册
- Pending → Running:Operation 开始执行
- Running → Succeeded:执行成功
- Running → Failed:执行失败
- Pending/Running → Cancelled:操作被取消
2.4 Operation 基类
csharp
public abstract class AsyncOperationBase
{
public EOperationStatus Status { get; protected set; }
public float Progress { get; protected set; }
public string Error { get; protected set; }
public bool IsDone => Status == EOperationStatus.Succeeded || Status == EOperationStatus.Failed || Status == EOperationStatus.Cancelled;
public event Action<AsyncOperationBase> OnCompleted;
public abstract void Start();
public abstract void Update();
public virtual void Destroy();
}
Status 详解:
Status 是 Operation 的当前状态。
Progress 详解:
Progress 是 Operation 的执行进度。
Error 详解:
Error 是 Operation 失败时的错误信息。
OnCompleted 详解:
OnCompleted 是 Operation 完成时触发的事件。
三、优先级队列
3.1 优先级队列的作用
YooAsset 使用优先级队列管理 Operation:
优先级队列的作用:
- 高优先级 Operation 优先执行
- 支持紧急资源的快速加载
- 灵活调度异步操作
3.2 优先级定义
csharp
public enum EOperationPriority
{
Low = 0,
BelowNormal = 3,
Normal = 5,
AboveNormal = 7,
High = 9,
Ultra = 10,
}
优先级详解:
- Low:低优先级
- BelowNormal:低于正常
- Normal:正常
- AboveNormal:高于正常
- High:高优先级
- Ultra:超高优先级
3.3 优先级队列的实现
csharp
public class PriorityQueue<T> where T : IComparable<T>
{
private List<T> _data;
public void Enqueue(T item)
{
_data.Add(item);
int childIndex = _data.Count - 1;
while (childIndex > 0)
{
int parentIndex = (childIndex - 1) / 2;
if (_data[childIndex].CompareTo(_data[parentIndex]) >= 0) break;
T tmp = _data[childIndex];
_data[childIndex] = _data[parentIndex];
_data[parentIndex] = tmp;
childIndex = parentIndex;
}
}
public T Dequeue()
{
int lastIndex = _data.Count - 1;
T frontItem = _data[0];
_data[0] = _data[lastIndex];
_data.RemoveAt(lastIndex);
// 下沉调整
// ...
return frontItem;
}
}
二叉堆实现详解:
使用二叉堆(Binary Heap)实现优先级队列。
入队操作详解:
入队时将元素添加到堆尾,然后上浮调整。
出队操作详解:
出队时取出堆顶元素,然后将堆尾元素移到堆顶,最后下沉调整。
3.4 优先级应用场景
关键资源优先加载:
使用高优先级加载关键资源,如玩家角色、UI 等。
后台资源低优先级加载:
使用低优先级加载后台资源,如未来的关卡资源。
动态调整优先级:
可以根据游戏状态动态调整 Operation 的优先级。
四、Operation 加载/卸载
4.1 加载流程
Operation 的加载流程:
markdown
Operation 加载流程
1. 创建 Operation
2. 设置 Operation 参数
3. 启动 Operation(Start)
4. OperationSystem 调度 Operation
5. 每帧调用 Update
6. Operation 完成
7. 触发完成回调
创建 Operation 详解:
开发者创建 Operation 实例并设置参数。
启动 Operation 详解:
调用 Start 方法启动 Operation。
调度 Operation 详解:
OperationSystem 调度 Operation,根据优先级决定执行顺序。
每帧 Update 详解:
OperationSystem 在每帧调用 Operation 的 Update 方法。
完成回调详解:
Operation 完成时触发 OnCompleted 事件。
4.2 加载实现
csharp
public class AssetLoadOperation : AsyncOperationBase
{
private ResourcePackage _package;
private string _location;
public override void Start()
{
Status = EOperationStatus.Running;
// 启动加载逻辑
}
public override void Update()
{
// 更新加载进度
Progress = CalculateProgress();
// 检查是否完成
if (IsLoadComplete())
{
Status = EOperationStatus.Succeeded;
OnCompleted?.Invoke(this);
}
}
}
Start 详解:
Start 方法启动加载逻辑,将状态设置为 Running。
Update 详解:
Update 方法在每帧被调用,更新加载进度并检查是否完成。
完成回调详解:
加载完成时触发 OnCompleted 事件。
4.3 取消流程
Operation 的取消流程:
markdown
Operation 取消流程
1. 调用 Cancel 方法
2. 设置状态为 Cancelled
3. 触发完成回调
Cancel 方法详解:
csharp
public class AsyncOperationBase
{
public virtual void Cancel()
{
if (Status == EOperationStatus.Succeeded || Status == EOperationStatus.Failed) return;
Status = EOperationStatus.Cancelled;
OnCompleted?.Invoke(this);
}
}
取消限制详解:
已完成的 Operation 不能被取消。
取消通知详解:
取消时触发 OnCompleted 事件,通知监听者。
4.4 销毁流程
Operation 的销毁流程:
markdown
Operation 销毁流程
1. 调用 Destroy 方法
2. 清理 Operation 资源
3. 从 OperationSystem 中移除
Destroy 方法详解:
csharp
public virtual void Destroy()
{
OnCompleted = null;
Status = EOperationStatus.None;
Progress = 0;
Error = null;
}
清理资源详解:
销毁时清理 Operation 占用的资源,如取消订阅、释放内存等。
从 OperationSystem 移除详解:
销毁的 Operation 需要从 OperationSystem 中移除,避免内存泄漏。
五、OperationSystem 调度器
5.1 OperationSystem 的作用
OperationSystem 是 YooAsset 异步操作的调度器:
调度器的作用:
- 管理所有 Operation
- 调度 Operation 的执行
- 维护 Operation 的优先级
- 处理 Operation 的完成回调
5.2 OperationSystem 的实现
csharp
public class OperationSystem
{
private List<AsyncOperationBase> _operations = new List<AsyncOperationBase>();
private List<AsyncOperationBase> _completeList = new List<AsyncOperationBase>();
private List<AsyncOperationBase> _destroyList = new List<AsyncOperationBase>();
public void ProcessOperation(AsyncOperationBase operation)
{
operation.Start();
_operations.Add(operation);
}
public void Update()
{
// 更新所有 Operation
for (int i = 0; i < _operations.Count; i++)
{
var op = _operations[i];
op.Update();
if (op.IsDone)
{
_completeList.Add(op);
}
}
// 处理完成的 Operation
ProcessCompletedOperations();
}
private void ProcessCompletedOperations()
{
foreach (var op in _completeList)
{
op.OnCompleted?.Invoke(op);
_destroyList.Add(op);
}
_completeList.Clear();
foreach (var op in _destroyList)
{
op.Destroy();
_operations.Remove(op);
}
_destroyList.Clear();
}
}
ProcessOperation 详解:
注册新的 Operation 到 OperationSystem。
Update 详解:
每帧调用 Update 方法,更新所有 Operation。
完成处理详解:
处理已完成的 Operation,触发回调并销毁。
5.3 OperationSystem 的时间片
csharp
public class OperationSystem
{
public float TimeSlice { get; set; } = 0.5f; // 0.5 毫秒
public void Update()
{
float startTime = Time.realtimeSinceStartup;
for (int i = 0; i < _operations.Count; i++)
{
_operations[i].Update();
if (Time.realtimeSinceStartup - startTime > TimeSlice)
break;
}
}
}
时间片的作用详解:
时间片限制 OperationSystem 在单帧内执行的最大时间,避免阻塞主线程。
时间片的应用详解:
开发者可以根据项目需求调整时间片大小。
5.4 OperationUpdater
csharp
public class OperationUpdater : MonoBehaviour
{
private void Update()
{
OperationSystem.Update();
}
}
OperationUpdater 的作用详解:
OperationUpdater 是 OperationSystem 的 MonoBehaviour 包装,在每帧调用 OperationSystem.Update。
DontDestroyOnLoad 详解:
OperationUpdater 使用 DontDestroyOnLoad 确保在场景切换时不被销毁。
六、总结
本章深入解析了 YooAsset 异步体系(OperationSystem)的源码实现,包括:
- Operation 概述:Operation 的概念、状态机、状态详解
- 优先级队列:优先级队列的作用、定义、实现、应用
- Operation 加载/卸载:加载流程、加载实现、取消流程、销毁流程
- OperationSystem 调度器:调度器的作用、实现、时间片、Updater
通过深入理解 OperationSystem 的实现,开发者可以更好地理解 YooAsset 的异步操作管理机制,并实现自定义的异步操作。
上一篇 :资源提供者(Provider 体系) 下一篇 :引用计数机制