mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-30 21:48:47 +00:00
refactor : 重构代码
This commit is contained in:
@@ -206,7 +206,8 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
StyleColor textColor;
|
StyleColor textColor;
|
||||||
var providerTableData = data as ProviderTableData;
|
var providerTableData = data as ProviderTableData;
|
||||||
if (providerTableData.ProviderInfo.Status == EOperationStatus.Failed.ToString())
|
if (providerTableData.ProviderInfo.Status == EOperationStatus.Failed.ToString() ||
|
||||||
|
providerTableData.ProviderInfo.Status == EOperationStatus.Aborted.ToString())
|
||||||
textColor = new StyleColor(Color.yellow);
|
textColor = new StyleColor(Color.yellow);
|
||||||
else
|
else
|
||||||
textColor = new StyleColor(Color.white);
|
textColor = new StyleColor(Color.white);
|
||||||
@@ -280,7 +281,8 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
StyleColor textColor;
|
StyleColor textColor;
|
||||||
var dependTableData = data as DependTableData;
|
var dependTableData = data as DependTableData;
|
||||||
if (dependTableData.BundleInfo.Status == EOperationStatus.Failed.ToString())
|
if (dependTableData.BundleInfo.Status == EOperationStatus.Failed.ToString() ||
|
||||||
|
dependTableData.BundleInfo.Status == EOperationStatus.Aborted.ToString())
|
||||||
textColor = new StyleColor(Color.yellow);
|
textColor = new StyleColor(Color.yellow);
|
||||||
else
|
else
|
||||||
textColor = new StyleColor(Color.white);
|
textColor = new StyleColor(Color.white);
|
||||||
|
|||||||
@@ -151,7 +151,8 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
StyleColor textColor;
|
StyleColor textColor;
|
||||||
var bundleTableData = data as BundleTableData;
|
var bundleTableData = data as BundleTableData;
|
||||||
if (bundleTableData.BundleInfo.Status == EOperationStatus.Failed.ToString())
|
if (bundleTableData.BundleInfo.Status == EOperationStatus.Failed.ToString() ||
|
||||||
|
bundleTableData.BundleInfo.Status == EOperationStatus.Aborted.ToString())
|
||||||
textColor = new StyleColor(Color.yellow);
|
textColor = new StyleColor(Color.yellow);
|
||||||
else
|
else
|
||||||
textColor = new StyleColor(Color.white);
|
textColor = new StyleColor(Color.white);
|
||||||
@@ -267,7 +268,8 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
StyleColor textColor;
|
StyleColor textColor;
|
||||||
var usingTableData = data as UsingTableData;
|
var usingTableData = data as UsingTableData;
|
||||||
if (usingTableData.ProviderInfo.Status == EOperationStatus.Failed.ToString())
|
if (usingTableData.ProviderInfo.Status == EOperationStatus.Failed.ToString() ||
|
||||||
|
usingTableData.ProviderInfo.Status == EOperationStatus.Aborted.ToString())
|
||||||
textColor = new StyleColor(Color.yellow);
|
textColor = new StyleColor(Color.yellow);
|
||||||
else
|
else
|
||||||
textColor = new StyleColor(Color.white);
|
textColor = new StyleColor(Color.white);
|
||||||
@@ -341,7 +343,8 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
StyleColor textColor;
|
StyleColor textColor;
|
||||||
var feferenceTableData = data as ReferenceTableData;
|
var feferenceTableData = data as ReferenceTableData;
|
||||||
if (feferenceTableData.BundleInfo.Status == EOperationStatus.Failed.ToString())
|
if (feferenceTableData.BundleInfo.Status == EOperationStatus.Failed.ToString() ||
|
||||||
|
feferenceTableData.BundleInfo.Status == EOperationStatus.Aborted.ToString())
|
||||||
textColor = new StyleColor(Color.yellow);
|
textColor = new StyleColor(Color.yellow);
|
||||||
else
|
else
|
||||||
textColor = new StyleColor(Color.white);
|
textColor = new StyleColor(Color.white);
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ namespace YooAsset.Editor
|
|||||||
{
|
{
|
||||||
StyleColor textColor;
|
StyleColor textColor;
|
||||||
var operationTableData = data as OperationTableData;
|
var operationTableData = data as OperationTableData;
|
||||||
if (operationTableData.OperationInfo.Status == EOperationStatus.Failed.ToString())
|
if (operationTableData.OperationInfo.Status == EOperationStatus.Failed.ToString() ||
|
||||||
|
operationTableData.OperationInfo.Status == EOperationStatus.Aborted.ToString())
|
||||||
textColor = new StyleColor(Color.yellow);
|
textColor = new StyleColor(Color.yellow);
|
||||||
else
|
else
|
||||||
textColor = new StyleColor(Color.white);
|
textColor = new StyleColor(Color.white);
|
||||||
@@ -479,7 +480,8 @@ namespace YooAsset.Editor
|
|||||||
// Status
|
// Status
|
||||||
{
|
{
|
||||||
StyleColor textColor;
|
StyleColor textColor;
|
||||||
if (operationInfo.Status == EOperationStatus.Failed.ToString())
|
if (operationInfo.Status == EOperationStatus.Failed.ToString() ||
|
||||||
|
operationInfo.Status == EOperationStatus.Aborted.ToString())
|
||||||
textColor = new StyleColor(Color.yellow);
|
textColor = new StyleColor(Color.yellow);
|
||||||
else
|
else
|
||||||
textColor = new StyleColor(Color.white);
|
textColor = new StyleColor(Color.white);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -78,13 +78,13 @@ namespace YooAsset
|
|||||||
public float Progress { get; protected set; }
|
public float Progress { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 任务逻辑是否完成(Status为Succeed或Failed)
|
/// 任务逻辑是否完成(Status为Succeed、Failed或Aborted)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsDone
|
public bool IsDone
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Status == EOperationStatus.Failed || Status == EOperationStatus.Succeed;
|
return Status == EOperationStatus.Succeed || Status == EOperationStatus.Failed || Status == EOperationStatus.Aborted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 终止异步任务
|
/// 终止异步任务(递归中止所有子任务)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void AbortOperation()
|
internal void AbortOperation()
|
||||||
{
|
{
|
||||||
@@ -299,7 +299,7 @@ namespace YooAsset
|
|||||||
if (IsDone == false)
|
if (IsDone == false)
|
||||||
{
|
{
|
||||||
InternalAbort();
|
InternalAbort();
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Aborted;
|
||||||
Error = "user abort";
|
Error = "user abort";
|
||||||
YooLogger.Warning($"Async operation {this.GetType().Name} has been aborted.");
|
YooLogger.Warning($"Async operation {this.GetType().Name} has been aborted.");
|
||||||
}
|
}
|
||||||
@@ -403,7 +403,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 等待异步执行完毕
|
/// 同步等待异步执行完毕(会阻塞当前线程)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void WaitForAsyncComplete()
|
public void WaitForAsyncComplete()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace YooAsset
|
|||||||
Failed,
|
Failed,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已中止
|
/// 已中止(用户主动取消)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Aborted,
|
Aborted,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 销毁包裹的所有任务
|
/// 清空并中止包裹的所有任务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void ClearPackageOperations(string packageName)
|
public static void ClearPackageOperations(string packageName)
|
||||||
{
|
{
|
||||||
|
|||||||
442
Assets/YooAsset/Runtime/OperationSystem/README.md
Normal file
442
Assets/YooAsset/Runtime/OperationSystem/README.md
Normal file
@@ -0,0 +1,442 @@
|
|||||||
|
# OperationSystem 异步操作模块
|
||||||
|
|
||||||
|
## 模块概述
|
||||||
|
|
||||||
|
OperationSystem 是 YooAsset 资源管理系统的**异步操作调度层**,负责管理和调度所有异步操作的生命周期。该模块提供了统一的异步操作抽象,支持协程、Task(async/await)、回调等多种异步编程模式,以及基于优先级的时间切片调度机制。
|
||||||
|
|
||||||
|
### 可见性说明
|
||||||
|
|
||||||
|
OperationSystem 属于 YooAsset Runtime 的内部基础模块,目录内 `OperationSystem`、`OperationScheduler` 等类型为 `internal`(仅供 YooAsset Runtime 内部程序集使用)。`AsyncOperationBase` 和 `EOperationStatus` 为 `public`,供上层和用户代码使用。
|
||||||
|
|
||||||
|
### 核心职责
|
||||||
|
|
||||||
|
- 异步操作生命周期管理(启动、更新、完成、中止)
|
||||||
|
- 基于优先级的调度排序
|
||||||
|
- 时间切片执行(防止主线程阻塞)
|
||||||
|
- 多包裹独立调度
|
||||||
|
- 父子任务依赖管理
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 边界与上层协作
|
||||||
|
|
||||||
|
OperationSystem 的职责是提供"统一异步操作抽象 + 优先级调度 + 时间切片执行"的基础能力:
|
||||||
|
|
||||||
|
- **本模块不负责具体业务逻辑**:具体的资源加载、下载等逻辑由子类实现
|
||||||
|
- **本模块不负责错误重试**:失败后的重试策略由上层或子类实现
|
||||||
|
- **本模块不负责资源释放**:资源的引用计数和卸载由 ResourceManager 管理
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 设计目标
|
||||||
|
|
||||||
|
| 目标 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| **统一抽象** | 所有异步操作继承 AsyncOperationBase,提供一致的 API |
|
||||||
|
| **多模式支持** | 支持协程(yield return)、Task(async/await)、回调三种异步模式 |
|
||||||
|
| **时间切片** | 可配置每帧最大执行时间,防止主线程卡顿 |
|
||||||
|
| **优先级调度** | 支持任务和调度器双层优先级,高优先级任务优先执行 |
|
||||||
|
| **多包裹隔离** | 每个资源包裹拥有独立调度器,互不干扰 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 架构概念
|
||||||
|
|
||||||
|
### 分层架构
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ 上层调用者 │
|
||||||
|
│ (ResourcePackage / ResourceManager) │
|
||||||
|
└─────────────────────────┬───────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌─────────────────────────▼───────────────────────────────┐
|
||||||
|
│ OperationSystem │
|
||||||
|
│ (静态调度系统) │
|
||||||
|
│ 管理所有调度器,提供时间切片机制 │
|
||||||
|
└─────────────────────────┬───────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌─────────────────────────▼───────────────────────────────┐
|
||||||
|
│ OperationScheduler │
|
||||||
|
│ (包裹调度器) │
|
||||||
|
│ 管理单个包裹的异步操作队列 │
|
||||||
|
└─────────────────────────┬───────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌─────────────────────────▼───────────────────────────────┐
|
||||||
|
│ AsyncOperationBase │
|
||||||
|
│ (异步操作基类) │
|
||||||
|
│ 定义操作生命周期和状态机 │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 核心组件
|
||||||
|
|
||||||
|
- **OperationSystem**: 静态调度系统,管理所有包裹调度器,提供时间切片执行机制
|
||||||
|
- **OperationScheduler**: 包裹调度器,管理单个包裹的异步操作队列和优先级排序
|
||||||
|
- **AsyncOperationBase**: 异步操作抽象基类,定义操作生命周期和多种异步编程接口
|
||||||
|
- **EOperationStatus**: 操作状态枚举,表示操作的当前状态
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 文件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
OperationSystem/
|
||||||
|
├── AsyncOperationBase.cs # 异步操作抽象基类
|
||||||
|
├── EOperationStatus.cs # 操作状态枚举
|
||||||
|
├── OperationScheduler.cs # 包裹调度器
|
||||||
|
├── OperationSystem.cs # 静态调度系统
|
||||||
|
└── README.md # 本文档
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 接口说明
|
||||||
|
|
||||||
|
### EOperationStatus(操作状态枚举)
|
||||||
|
|
||||||
|
定义异步操作的生命周期状态。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public enum EOperationStatus
|
||||||
|
{
|
||||||
|
None, // 未开始
|
||||||
|
Processing, // 处理中
|
||||||
|
Succeed, // 已成功
|
||||||
|
Failed, // 已失败
|
||||||
|
Aborted // 已中止(用户主动取消)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### AsyncOperationBase(异步操作基类)
|
||||||
|
|
||||||
|
所有异步操作的抽象基类,实现 `IEnumerator`(协程支持)和 `IComparable<T>`(优先级排序)。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public abstract class AsyncOperationBase : IEnumerator, IComparable<AsyncOperationBase>
|
||||||
|
{
|
||||||
|
// 状态属性
|
||||||
|
public EOperationStatus Status { get; } // 当前状态
|
||||||
|
public bool IsDone { get; } // 是否完成(Succeed/Failed/Aborted)
|
||||||
|
public string Error { get; } // 错误信息
|
||||||
|
public float Progress { get; } // 进度(0-1)
|
||||||
|
public uint Priority { get; set; } // 优先级(值越大越优先)
|
||||||
|
|
||||||
|
// 异步编程支持
|
||||||
|
public Task Task { get; } // 用于 async/await
|
||||||
|
public event Action<AsyncOperationBase> Completed; // 完成回调
|
||||||
|
|
||||||
|
// 同步等待
|
||||||
|
public void WaitForAsyncComplete(); // 同步等待完成(阻塞当前线程)
|
||||||
|
|
||||||
|
// 调试信息(仅 DEBUG 模式有效)
|
||||||
|
public string StartTime { get; } // 开始时间(HH:MM:SS)
|
||||||
|
public long ElapsedMS { get; } // 耗时(毫秒)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 子类必须实现的方法
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 启动时调用(必须实现)
|
||||||
|
internal abstract void InternalStart();
|
||||||
|
|
||||||
|
// 每帧更新(必须实现)
|
||||||
|
internal abstract void InternalUpdate();
|
||||||
|
|
||||||
|
// 中止时调用(可选实现)
|
||||||
|
internal virtual void InternalAbort() { }
|
||||||
|
|
||||||
|
// 同步等待实现(可选实现,不实现则抛出异常)
|
||||||
|
internal virtual void InternalWaitForAsyncComplete();
|
||||||
|
|
||||||
|
// 获取操作描述(可选实现,用于调试)
|
||||||
|
internal virtual string InternalGetDescription();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 核心类说明
|
||||||
|
|
||||||
|
### OperationSystem
|
||||||
|
|
||||||
|
静态调度系统,管理所有包裹的调度器,提供全局时间切片机制。
|
||||||
|
|
||||||
|
**主要功能:**
|
||||||
|
- 管理多个包裹调度器的生命周期
|
||||||
|
- 提供全局时间切片预算控制
|
||||||
|
- 按优先级更新各调度器
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
internal static class OperationSystem
|
||||||
|
{
|
||||||
|
// 时间切片配置
|
||||||
|
public static long MaxTimeSlice { get; set; } // 每帧最大执行时间(毫秒)
|
||||||
|
public static bool IsBusy { get; } // 当前帧时间切片是否已用完
|
||||||
|
|
||||||
|
// 生命周期
|
||||||
|
public static void Initialize(); // 初始化系统
|
||||||
|
public static void Update(); // 每帧更新
|
||||||
|
public static void DestroyAll(); // 销毁系统
|
||||||
|
|
||||||
|
// 调度器管理
|
||||||
|
public static OperationScheduler CreatePackageScheduler(string packageName, uint priority);
|
||||||
|
public static void DestroyPackageScheduler(string packageName);
|
||||||
|
public static void ClearPackageOperations(string packageName);
|
||||||
|
|
||||||
|
// 任务管理
|
||||||
|
public static void StartOperation(string packageName, AsyncOperationBase operation);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### OperationScheduler
|
||||||
|
|
||||||
|
包裹调度器,管理单个包裹的异步操作队列。
|
||||||
|
|
||||||
|
**主要功能:**
|
||||||
|
- 管理操作队列(待处理队列 + 执行队列)
|
||||||
|
- 按优先级排序操作
|
||||||
|
- 更新和完成操作
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
internal class OperationScheduler : IComparable<OperationScheduler>
|
||||||
|
{
|
||||||
|
public string PackageName { get; } // 所属包裹名称
|
||||||
|
public uint Priority { get; set; } // 调度器优先级
|
||||||
|
public int CreationOrder { get; } // 创建顺序(同优先级稳定排序)
|
||||||
|
|
||||||
|
public void StartOperation(AsyncOperationBase operation); // 启动操作
|
||||||
|
public void Update(); // 更新调度
|
||||||
|
public void ClearAll(); // 清空并中止所有任务
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
### 协程方式
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
IEnumerator LoadAssetCoroutine()
|
||||||
|
{
|
||||||
|
var operation = package.LoadAssetAsync<GameObject>("Assets/Prefab.prefab");
|
||||||
|
yield return operation;
|
||||||
|
|
||||||
|
if (operation.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
GameObject prefab = operation.AssetObject as GameObject;
|
||||||
|
Instantiate(prefab);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"加载失败: {operation.Error}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### async/await 方式
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
async void LoadAssetAsync()
|
||||||
|
{
|
||||||
|
var operation = package.LoadAssetAsync<GameObject>("Assets/Prefab.prefab");
|
||||||
|
await operation.Task;
|
||||||
|
|
||||||
|
if (operation.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
GameObject prefab = operation.AssetObject as GameObject;
|
||||||
|
Instantiate(prefab);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"加载失败: {operation.Error}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 回调方式
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
void LoadAssetWithCallback()
|
||||||
|
{
|
||||||
|
var operation = package.LoadAssetAsync<GameObject>("Assets/Prefab.prefab");
|
||||||
|
operation.Completed += OnLoadCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnLoadCompleted(AsyncOperationBase op)
|
||||||
|
{
|
||||||
|
var operation = op as AssetHandle;
|
||||||
|
if (operation.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
GameObject prefab = operation.AssetObject as GameObject;
|
||||||
|
Instantiate(prefab);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"加载失败: {operation.Error}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 同步等待方式
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
void LoadAssetSync()
|
||||||
|
{
|
||||||
|
var operation = package.LoadAssetAsync<GameObject>("Assets/Prefab.prefab");
|
||||||
|
operation.WaitForAsyncComplete(); // 注意:会阻塞当前线程
|
||||||
|
|
||||||
|
if (operation.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
GameObject prefab = operation.AssetObject as GameObject;
|
||||||
|
Instantiate(prefab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 设置优先级
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 高优先级任务优先执行
|
||||||
|
var highPriorityOp = package.LoadAssetAsync<GameObject>("ImportantAsset");
|
||||||
|
highPriorityOp.Priority = 100;
|
||||||
|
|
||||||
|
var lowPriorityOp = package.LoadAssetAsync<GameObject>("BackgroundAsset");
|
||||||
|
lowPriorityOp.Priority = 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 配置时间切片
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 设置每帧最大执行时间为 10 毫秒
|
||||||
|
OperationSystem.MaxTimeSlice = 10;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 设计模式
|
||||||
|
|
||||||
|
### 模板方法模式
|
||||||
|
|
||||||
|
`AsyncOperationBase` 定义操作的骨架流程,子类实现具体步骤:
|
||||||
|
|
||||||
|
```
|
||||||
|
AsyncOperationBase (抽象类)
|
||||||
|
│
|
||||||
|
├── StartOperation() ──► InternalStart() [子类实现]
|
||||||
|
├── UpdateOperation() ──► InternalUpdate() [子类实现]
|
||||||
|
├── AbortOperation() ──► InternalAbort() [子类可选实现]
|
||||||
|
└── WaitForAsyncComplete() ──► InternalWaitForAsyncComplete() [子类可选实现]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 状态机模式
|
||||||
|
|
||||||
|
操作生命周期通过状态机管理:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────┐ StartOperation() ┌────────────┐
|
||||||
|
│ None │ ────────────────────► │ Processing │
|
||||||
|
└──────┘ └─────┬──────┘
|
||||||
|
│ UpdateOperation()
|
||||||
|
┌───────────────┼───────────────┐
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌─────────┐ ┌──────────┐ ┌─────────┐
|
||||||
|
│ Succeed │ │ Failed │ │ Aborted │
|
||||||
|
└─────────┘ └──────────┘ └─────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 组合模式
|
||||||
|
|
||||||
|
支持父子任务关系,父任务可以管理多个子任务:
|
||||||
|
|
||||||
|
```
|
||||||
|
ParentOperation
|
||||||
|
│
|
||||||
|
├── ChildOperation1
|
||||||
|
├── ChildOperation2
|
||||||
|
└── ChildOperation3
|
||||||
|
```
|
||||||
|
|
||||||
|
### 时间切片模式
|
||||||
|
|
||||||
|
防止主线程阻塞,每帧限制执行时间:
|
||||||
|
|
||||||
|
```
|
||||||
|
每帧 Update()
|
||||||
|
│
|
||||||
|
├── 记录帧开始时间
|
||||||
|
│
|
||||||
|
├── 遍历调度器(按优先级)
|
||||||
|
│ │
|
||||||
|
│ ├── 遍历操作(按优先级)
|
||||||
|
│ │ │
|
||||||
|
│ │ └── 检查 IsBusy ──► 超时则跳出
|
||||||
|
│ │
|
||||||
|
│ └── 检查 IsBusy ──► 超时则跳出
|
||||||
|
│
|
||||||
|
└── 结束
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 类继承关系
|
||||||
|
|
||||||
|
```
|
||||||
|
AsyncOperationBase (抽象基类)
|
||||||
|
│
|
||||||
|
├── InitializePackageOperation (包裹初始化)
|
||||||
|
├── LoadManifestOperation (清单加载)
|
||||||
|
├── DownloaderOperation (下载器操作)
|
||||||
|
├── UnloadAllAssetsOperation (卸载所有资源)
|
||||||
|
├── DestroyPackageOperation (销毁包裹)
|
||||||
|
│
|
||||||
|
├── ProviderOperation (资源提供者基类)
|
||||||
|
│ ├── AssetProvider (单个资源)
|
||||||
|
│ ├── SubAssetsProvider (子资源)
|
||||||
|
│ ├── AllAssetsProvider (全部资源)
|
||||||
|
│ └── SceneProvider (场景)
|
||||||
|
│
|
||||||
|
└── ... (更多子类)
|
||||||
|
|
||||||
|
OperationScheduler
|
||||||
|
└── 管理 List<AsyncOperationBase>
|
||||||
|
|
||||||
|
OperationSystem
|
||||||
|
└── 管理 Dictionary<string, OperationScheduler>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 调试信息
|
||||||
|
|
||||||
|
### 调试属性
|
||||||
|
|
||||||
|
在 DEBUG 模式下,`AsyncOperationBase` 提供以下调试信息:
|
||||||
|
|
||||||
|
| 属性 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `StartTime` | `string` | 操作开始时间(格式:HH:MM:SS) |
|
||||||
|
| `ElapsedMS` | `long` | 操作耗时(毫秒) |
|
||||||
|
|
||||||
|
### DiagnosticOperationInfo
|
||||||
|
|
||||||
|
通过 `GetDebugOperationInfo()` 获取操作的诊断信息结构体,包含:
|
||||||
|
|
||||||
|
- 操作名称、描述
|
||||||
|
- 优先级、进度、状态
|
||||||
|
- 开始时间、耗时
|
||||||
|
- 子操作列表(递归)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **主线程调用**:所有操作的创建和更新应在 Unity 主线程进行
|
||||||
|
2. **同步等待风险**:`WaitForAsyncComplete()` 会阻塞当前线程,可能导致死锁,谨慎使用
|
||||||
|
3. **优先级变更**:修改 `Priority` 后,下一帧才会重新排序
|
||||||
|
4. **时间切片粒度**:时间切片检测在每个操作更新后进行,单个操作内部不会被中断
|
||||||
|
5. **子任务中止**:调用 `AbortOperation()` 会递归中止所有子任务
|
||||||
|
6. **回调异常隔离**:完成回调中的异常会被捕获并记录,不会影响其他回调
|
||||||
|
7. **状态不可逆**:一旦进入终态(Succeed/Failed/Aborted),状态不可更改
|
||||||
|
8. **Progress 语义**:`Progress` 在操作完成时自动设置为 1.0f,子类应在处理过程中更新进度
|
||||||
7
Assets/YooAsset/Runtime/OperationSystem/README.md.meta
Normal file
7
Assets/YooAsset/Runtime/OperationSystem/README.md.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2afe3d5ffb611b241919112b40d9c7d0
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
public class DestroyPackageOperation : AsyncOperationBase
|
public class DestroyPackageOperation : AsyncOperationBase
|
||||||
@@ -39,6 +39,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
case EOperationStatus.None:
|
case EOperationStatus.None:
|
||||||
case EOperationStatus.Failed:
|
case EOperationStatus.Failed:
|
||||||
|
case EOperationStatus.Aborted:
|
||||||
_steps = ESteps.DestroyPackage;
|
_steps = ESteps.DestroyPackage;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -900,6 +900,9 @@ namespace YooAsset
|
|||||||
case EOperationStatus.Failed:
|
case EOperationStatus.Failed:
|
||||||
string error = _initializeOp == null ? string.Empty : _initializeOp.Error;
|
string error = _initializeOp == null ? string.Empty : _initializeOp.Error;
|
||||||
throw new YooPackageException(PackageName, $"Resource package initialization failed. Error: {error}");
|
throw new YooPackageException(PackageName, $"Resource package initialization failed. Error: {error}");
|
||||||
|
|
||||||
|
case EOperationStatus.Aborted:
|
||||||
|
throw new YooPackageException(PackageName, "Resource package initialization was aborted.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user