概述(Overview)
UniTaskDemo 是一个专注于展示 UniTask(Cysharp.Threading.Tasks)在 Unity 中的各种高级用法与最佳实践的示例类。
主要演示内容包括:
- 异步方法通过委托跨脚本传递与调用
- 按钮点击的异步流(AsyncEnumerable)处理
- 使用异步 LINQ 操作点击事件(Take、Where、ForEachAsync 等)
- 不同方式实现“等待指定次数点击”的逻辑
- 异步 Update 循环(EveryUpdate)
- 取消令牌(CancellationToken)的使用场景
- UniTask 事件订阅(Subscribe)与延迟组合
- UniTaskManager(自定义任务管理器)的基本使用示例
适用于需要精细控制异步流程、事件流处理、取消支持的场景(如引导流程、加载、交互序列、多阶段操作等)。
方法一览(API Index)
| 方法名 | 访问级别 | 异步 | 返回类型 | 主要功能 | 典型用途 |
|---|---|---|---|---|---|
| DoSomethingAsync | private | 是 | UniTask | 连续等待三次按钮点击并打印日志 | 基础多阶段点击等待示例 |
| UpdateDemo | private | 是 | UniTask | 异步方式实现每帧 Update | 替代传统 Update 的异步写法 |
| EveryTwoClick | private | 是 | UniTask | 每两次点击触发一次逻辑 | 演示异步流 + Where 筛选 |
| ThreeClick1 | private | 是 | UniTask | 使用 AsyncClickEventHandler 等待3次点击 | 传统顺序等待方式 |
| ThreeClick2 | private | 是 | UniTask | 使用 Take(3) + LastAsync 等待3次点击 | 简洁等待固定次数点击 |
| ThreeClick3 | private | 是 | UniTask | 使用 Take(3) + ForEachAsync 监听3次点击 | 每次点击都执行操作 + 最后总结 |
| DelayDemo | private | 是 | UniTask | 订阅点击事件,点击后延时1秒执行 | 演示 Subscribe + 延迟组合 |
| TaskDemo | public static | 是 | Func<CancellationToken, UniTask> | 暴露给外部的异步任务委托 | 跨脚本/模块调用异步流程 |
| ActionDemo | public static | 否 | Action | 暴露给外部的同步委托(未使用) | — |
静态字段 / 公开接口
TaskDemo
/// <summary>
/// 可被外部脚本调用的异步任务委托
/// 支持 CancellationToken 取消
/// </summary>
public static Func<CancellationToken, UniTask> TaskDemo;
初始化位置:通常在 Awake 中赋值
典型用法(其他脚本):
UniTaskDemo.TaskDemo?.Invoke(cts.Token).Forget();
核心方法详情
DoSomethingAsync
/// <summary>
/// 连续等待用户点击三次按钮,每次点击打印对应日志
/// </summary>
/// <param name="ct">用于取消的令牌</param>
private async UniTask DoSomethingAsync(CancellationToken ct)
{
await okButton.OnClickAsync2D(ct);
Debug.Log("第一次点击");
await okButton.OnClickAsync2D(ct);
Debug.Log("第二次点击");
await okButton.OnClickAsync2D(ct);
Debug.Log("第三次点击");
}
最基础的顺序等待多次点击示例。
UpdateDemo
/// <summary>
/// 使用 UniTask.EveryUpdate() 实现异步每帧循环
/// 可通过 CancellationToken 优雅停止
/// </summary>
private async UniTask UpdateDemo(CancellationToken ctk)
{
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate().WithCancellation(ctk))
{
Debug.Log("Update() " + Time.frameCount);
}
}
替代传统 Update() 的现代写法,支持取消。
EveryTwoClick
/// <summary>
/// 每两次点击才执行一次逻辑(使用 Where 筛选偶数索引)
/// </summary>
private async UniTask EveryTwoClick(CancellationToken ctk)
{
await okButton.OnClickAsAsyncEnumerable()
.Where((x, i) => i % 2 == 0)
.ForEachAsync(_ => { Debug.Log("click"); }, cancellationToken: ctk);
}
展示如何对点击事件流进行过滤。
ThreeClick1(使用事件处理器)
/// <summary>
/// 使用 GetAsyncClickEventHandler 顺序等待三次点击
/// </summary>
private async UniTask ThreeClick1(CancellationToken ctk)
{
using var handler = okButton.GetAsyncClickEventHandler(ctk);
await handler.OnClickAsync();
await handler.OnClickAsync();
await handler.OnClickAsync();
Debug.Log("点击三次");
}
最直观的顺序写法,推荐在逻辑清晰时使用。
ThreeClick2(使用 Take + LastAsync)
/// <summary>
/// 等待正好三次点击后继续(不关心中间过程)
/// </summary>
private async UniTask ThreeClick2(CancellationToken ctk)
{
await okButton.OnClickAsAsyncEnumerable()
.Take(3)
.LastAsync(cancellationToken: ctk);
Debug.Log("点击三次");
}
最简洁的“等待三次点击”写法。
ThreeClick3(每次点击都响应)
/// <summary>
/// 等待三次点击,每点击一次都打印,结束后总结
/// </summary>
private async UniTask ThreeClick3(CancellationToken ctk)
{
await okButton.OnClickAsAsyncEnumerable()
.Take(3)
.ForEachAsync(_ => { Debug.Log("每次点击"); }, cancellationToken: ctk);
Debug.Log("三次点击完成");
}
适合需要在每次点击时都有反馈的场景。
DelayDemo(订阅 + 延迟)
/// <summary>
/// 每次点击后延迟1秒再执行操作
/// </summary>
private async UniTask DelayDemo(CancellationToken ctk)
{
okButton.OnClickAsAsyncEnumerable().Subscribe(async x =>
{
await UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: ctk);
Debug.Log("延时结束");
});
}
展示事件订阅与异步延迟的组合使用。
UniTaskManager 使用示例(代码中注释部分)
// 创建带 ID 的任务
var (id, cts) = UniTaskManager.CreateIdTask();
DoSomethingAsync(cts.Token).Forget();
// 取消指定任务
UniTaskManager.CancelIdTask(id);
// 创建带字符串标识的任务
var (key, cts2) = UniTaskManager.CreateStrTask("LoadScene");
DoSomethingAsync(cts2.Token).Forget();
// 取消全部任务
UniTaskManager.CancelAllTasks();