12.UniTask监听UGUI

12.UI监听


12.1 知识点

使用 UniTask 异步监听 UI 事件

在本篇博客中,我们将介绍如何通过 UniTask 高效地处理 Unity UI 事件监听。通过对按钮点击、输入框编辑、Toggle 与 Slider 数值变化等事件的异步监听,能够使项目代码更加简洁和高效。下面将结合具体代码示例详细讲解各个场景的实现方式。

测试脚本

using System;
using Cysharp.Threading.Tasks;
using System.Threading;
using UnityEngine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks.Linq; // 引入异步 LINQ 支持

// 注释说明:若要注册事件并使用异步的 lambda,请勿使用 async void,
// 可使用 UniTask.Action 或 UniTask.UnityAction 通过 async UniTaskVoid lambda 创建委托。
// 示例:
// UniTask.Action(
//     async () =>
//     {
//         Debug.Log("aa");
//         await UniTask.Delay(1000);
//     }
// );

// 注释说明:按钮点击事件可通过 OnClickAsync 转换为异步事件,其他 UI 组件类似。
// UniTask 提供了 GetCancellationTokenOnDestroy() 方法用于管理生命周期。
public class Lesson12_UI监听 : MonoBehaviour
{
    public Button btn1;
    public Button btn2;
    public Button btn3;
    public Button btn4;
    public InputField inputField;
    public Toggle toggle; // 新增 Toggle 组件
    public Slider slider; // 新增 Slider 组件

    void Start()
    {
        // 示例一:启动对 btn1 的不同监听方式
        // 只能响应一次点击
        OnClickBtn1AwaitOne().Forget();
        // 持续监听点击事件
        OnClickBtn1AwaitMore(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例二:对 btn2 采用不同的监听和处理方式监听按钮点击间隔 判断是单击还是双击
        OnClickBtn2UniTask(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例三:使用异步 LINQ 监听 btn3 三次点击 只会监听一次三连点击
        OnClickBtn3TripleClick(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例四:使用事件排队处理 btn4 点击事件
        OnClickBtn4QueueEvents(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例五:监听输入框结束编辑事件
        OnInputFieldEndEdit(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例六:监听 Toggle 值变化(异步流,实时输出变化值)
        OnToggleValueChangedAsync(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例七:监听 Slider 值变化(异步流,每次变化输出当前值)
        OnSliderValueChangedAsync(this.GetCancellationTokenOnDestroy()).Forget();
    }

    /// <summary>
    /// 该方法监听按钮的点击事件,但只能响应一次点击。
    /// 因为 await 语句只会执行一次,之后不会再监听点击事件。
    /// </summary>
    private async UniTaskVoid OnClickBtn1AwaitOne()
    {
        // 等待 btn1 被点击
        await btn1.OnClickAsync();
        Debug.Log("OnClickBtn1AwaitOne 再次点击无效:" + Time.time);
    }

    /// <summary>
    /// 该方法可以持续监听按钮的点击事件。
    /// 每次按钮被点击时,都会输出当前的时间。
    /// </summary>
    /// <param name="cancellationToken">用于取消异步操作的 CancellationToken,可通过 GetCancellationTokenOnDestroy 方法获取。</param>
    private async UniTaskVoid OnClickBtn1AwaitMore(CancellationToken cancellationToken)
    {
        // 进入无限循环,持续监听按钮点击事件
        while (true)
        {
            // 获取 btn1 点击事件的异步任务,传入取消令牌
            var btnUniTask = btn1.OnClickAsync(cancellationToken);

            // 等待 btn1 点击事件完成
            await btnUniTask;

            // 按钮点击后,输出日志显示点击时间
            Debug.Log("OnClickBtn1AwaitMore:" + Time.time);
        }
    }

    /// <summary>
    /// 该方法使用 UniTask 处理 btn2 的点击事件,判断是单击还是双击。
    /// </summary>
    /// <param name="cancellationToken"></param>
    private async UniTaskVoid OnClickBtn2UniTask(CancellationToken cancellationToken)
    {
        // 进入无限循环,持续处理 btn2 的点击事件
        while (true)
        {
            // 获取 btn2 第一次点击事件的异步任务
            var firstClickUniTask = btn2.OnClickAsync(cancellationToken);
            // 等待 btn2 第一次点击事件完成
            await firstClickUniTask;
            // 输出第一次点击的日志信息
            Debug.Log("OnClickBtn2UniTask 第1次点击");

            // 获取 btn2 第二次点击事件的异步任务
            var secondClickUniTask = btn2.OnClickAsync(cancellationToken);
            // 判断是单击还是双击,即判断指定时间内是否又点击了,也就是判断第二次点击和等待 1 秒这两个任务发生的先后顺序
            int index = await UniTask.WhenAny(secondClickUniTask,
                UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cancellationToken));

            // 根据 index 判断是第二次点击先发生还是等待 1 秒先完成
            if (index == 0)
            {
                // 若 index 为 0,说明第二次点击先发生,时间间隔不超过 1 秒
                Debug.Log("OnClickBtn2UniTask 时间间隔不超过1");
            }
            else
            {
                // 若 index 不为 0,说明等待 1 秒先完成,时间间隔超过 1 秒
                Debug.Log("OnClickBtn2UniTask 时间间隔超过1");
            }
        }
    }

    /// <summary>
    /// 该方法使用异步 LINQ 监听 btn3 三次点击。
    /// 注意:该方法只会监听一次三连点击,不会持续监听。
    /// 如果需要持续监听,需要自己加while
    /// </summary>
    /// <param name="cancellationToken"></param>
    private async UniTaskVoid OnClickBtn3TripleClick(CancellationToken cancellationToken)
    {
        // 使用异步 LINQ 等待 btn3 被点击三次
        // await btn3.OnClickAsAsyncEnumerable().Take(3).LastAsync(cancellationToken);
        await btn3.OnClickAsAsyncEnumerable().Take(3)
            .ForEachAsync(_ => { Debug.Log("OnClickBtn3TripleClick: 每次点击触发"); }, cancellationToken);

        // // index从0开始 第一次点击index会是0 所以取到的是0 1 2 index为2时 也就是第三次点击 所以会输出三次点击完成
        // var asyncEnumerable = btn3.OnClickAsAsyncEnumerable();
        // await asyncEnumerable.Take(3).ForEachAsync
        // ((_, index) =>
        // {
        //     if (cancellationToken.IsCancellationRequested) return;
        //
        //     if (index == 0)
        //     {
        //         Debug.Log(0);
        //     }
        //     else if (index == 1)
        //     {
        //         Debug.Log(1);
        //     }
        //     else
        //     {
        //         Debug.Log(2);
        //     }
        // }, cancellationToken);

        Debug.Log("OnClickBtn3TripleClick: 三次点击完成");
    }

    /// <summary>
    /// 该方法使用事件排队处理 btn4 点击事件。
    /// </summary>
    /// <param name="cancellationToken"></param>
    private async UniTaskVoid OnClickBtn4QueueEvents(CancellationToken cancellationToken)
    {
        // 对 btn4 的点击事件进行排队处理
        // 每次点击事件都会被添加到队列中,然后依次处理
        // 比如如下示例中 要等三秒才能处理下一个点击事件
        // 处理完成后,队列中的事件会被移除
        int count = 0;
        await btn4.OnClickAsAsyncEnumerable().Queue().ForEachAwaitAsync(async _ =>
        {
            Debug.Log($"OnClickBtn4QueueEvents: 开始处理点击事件{count}");
            await UniTask.Delay(TimeSpan.FromSeconds(3), cancellationToken: cancellationToken);
            Debug.Log($"OnClickBtn4QueueEvents: 点击事件{count}处理完成");
            count++;
        }, cancellationToken);
    }

    /// <summary>
    /// 该方法监听输入框结束编辑事件。
    /// </summary>
    /// <param name="cancellationToken"></param>
    private async UniTaskVoid OnInputFieldEndEdit(CancellationToken cancellationToken)
    {
        // 监听输入框结束编辑事件
        await foreach (var text in inputField.OnEndEditAsAsyncEnumerable().WithCancellation(cancellationToken))
        {
            Debug.Log($"OnInputFieldEndEdit: 输入框结束编辑,输入内容为: {text}");
        }
    }

    /// <summary>
    /// 示例六:监听 Toggle 的值变化事件,并在每次变化时输出当前值
    /// </summary>
    private async UniTaskVoid OnToggleValueChangedAsync(CancellationToken cancellationToken)
    {
        await toggle.OnValueChangedAsAsyncEnumerable(cancellationToken)
            .ForEachAsync(value => { Debug.Log("Toggle 值变化:" + value); });
    }

    /// <summary>
    /// 示例七:监听 Slider 的值变化事件,并在每次变化时输出当前值
    /// </summary>
    private async UniTaskVoid OnSliderValueChangedAsync(CancellationToken cancellationToken)
    {
        await slider.OnValueChangedAsAsyncEnumerable(cancellationToken)
            .ForEachAsync(value => { Debug.Log("Slider 当前值:" + value); });
    }
}

该脚本主要演示了以下功能:

  • 按钮点击事件:分别展示了仅响应一次点击、持续监听点击、以及通过双击判断操作。
  • 异步 LINQ 操作:使用异步 LINQ 实现对按钮连续点击次数的监听。
  • 事件排队处理:对按钮点击事件进行排队,确保每个事件按顺序依次处理。
  • UI 组件事件监听:包括输入框结束编辑、Toggle 状态变化以及 Slider 数值变化的实时监听。

代码中充分利用了 UniTask 的异步流和取消令牌,确保在 MonoBehaviour 销毁时能正确取消异步操作,避免内存泄漏或异常。

示例一:按钮不同监听方式

使用 OnClickBtn1AwaitOne 方法,仅等待按钮被点击一次,后续点击不再响应。这种方式适用于需要一次性操作的场景。

private async UniTaskVoid OnClickBtn1AwaitOne()
{
    // 等待 btn1 被点击
    await btn1.OnClickAsync();
    Debug.Log("OnClickBtn1AwaitOne 再次点击无效:" + Time.time);
}

通过 OnClickBtn1AwaitMore 方法实现无限循环,每次点击按钮都会记录当前时间,适合需要实时响应用户点击的情况。

private async UniTaskVoid OnClickBtn1AwaitMore(CancellationToken cancellationToken)
{
    // 进入无限循环,持续监听按钮点击事件
    while (true)
    {
        // 获取 btn1 点击事件的异步任务,传入取消令牌
        var btnUniTask = btn1.OnClickAsync(cancellationToken);
        // 等待 btn1 点击事件完成
        await btnUniTask;
        // 按钮点击后输出日志显示点击时间
        Debug.Log("OnClickBtn1AwaitMore:" + Time.time);
    }
}

示例二:判断单击与双击

OnClickBtn2UniTask 方法中,首先等待第一次点击,然后在 1 秒内判断是否有第二次点击,从而区分单击和双击操作。

private async UniTaskVoid OnClickBtn2UniTask(CancellationToken cancellationToken)
{
    while (true)
    {
        // 等待第一次点击
        var firstClickUniTask = btn2.OnClickAsync(cancellationToken);
        await firstClickUniTask;
        Debug.Log("OnClickBtn2UniTask 第1次点击");

        // 等待第二次点击或 1 秒超时
        int index = await UniTask.WhenAny(
            btn2.OnClickAsync(cancellationToken),
            UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cancellationToken)
        );

        if (index == 0)
        {
            // 第二次点击在 1 秒内发生
            Debug.Log("OnClickBtn2UniTask 时间间隔不超过1");
        }
        else
        {
            // 1 秒超时,视为单击
            Debug.Log("OnClickBtn2UniTask 时间间隔超过1");
        }
    }
}

示例三:异步 LINQ 监听三连点击

使用异步 LINQ 操作,在 OnClickBtn3TripleClick 方法中等待按钮被点击三次后再执行后续代码,适用于需要捕捉用户快速连续操作的场景。

/// <summary>
/// 该方法使用异步 LINQ 监听 btn3 三次点击。
/// 注意:该方法只会监听一次三连点击,不会持续监听。
/// 如果需要持续监听,需要自己加while
/// </summary>
/// <param name="cancellationToken"></param>
private async UniTaskVoid OnClickBtn3TripleClick(CancellationToken cancellationToken)
{
    // 使用异步 LINQ 等待 btn3 被点击三次
    // await btn3.OnClickAsAsyncEnumerable().Take(3).LastAsync(cancellationToken);
    await btn3.OnClickAsAsyncEnumerable().Take(3)
        .ForEachAsync(_ => { Debug.Log("OnClickBtn3TripleClick: 每次点击触发"); }, cancellationToken);

    // // index从0开始 第一次点击index会是0 所以取到的是0 1 2 index为2时 也就是第三次点击 所以会输出三次点击完成
    // var asyncEnumerable = btn3.OnClickAsAsyncEnumerable();
    // await asyncEnumerable.Take(3).ForEachAsync
    // ((_, index) =>
    // {
    //     if (cancellationToken.IsCancellationRequested) return;
    //
    //     if (index == 0)
    //     {
    //         Debug.Log(0);
    //     }
    //     else if (index == 1)
    //     {
    //         Debug.Log(1);
    //     }
    //     else
    //     {
    //         Debug.Log(2);
    //     }
    // }, cancellationToken);

    Debug.Log("OnClickBtn3TripleClick: 三次点击完成");
}

示例四:事件排队处理

OnClickBtn4QueueEvents 方法中,通过事件排队的方式处理按钮点击,每次点击事件处理之间等待固定时间,确保事件顺序执行而不会互相干扰。

private async UniTaskVoid OnClickBtn4QueueEvents(CancellationToken cancellationToken)
{
    int count = 0;
    await btn4.OnClickAsAsyncEnumerable().Queue().ForEachAwaitAsync(async _ =>
    {
        Debug.Log($"OnClickBtn4QueueEvents: 开始处理点击事件{count}");
        await UniTask.Delay(TimeSpan.FromSeconds(3), cancellationToken: cancellationToken);
        Debug.Log($"OnClickBtn4QueueEvents: 点击事件{count}处理完成");
        count++;
    }, cancellationToken);
}

示例五:监听输入框结束编辑事件

使用 OnInputFieldEndEdit 方法,通过异步流实时监听输入框结束编辑事件,并输出用户输入的内容。此方式适合需要捕捉用户输入并即时反馈的场景。

private async UniTaskVoid OnInputFieldEndEdit(CancellationToken cancellationToken)
{
    // 监听输入框结束编辑事件
    await foreach (var text in inputField.OnEndEditAsAsyncEnumerable().WithCancellation(cancellationToken))
    {
        Debug.Log($"OnInputFieldEndEdit: 输入框结束编辑,输入内容为: {text}");
    }
}

示例六:监听 Toggle 值变化

OnToggleValueChangedAsync 方法中,通过异步流监听 Toggle 的值变化事件,每次变化时输出当前值,使状态变更能够及时反馈到日志中。

private async UniTaskVoid OnToggleValueChangedAsync(CancellationToken cancellationToken)
{
    await toggle.OnValueChangedAsAsyncEnumerable(cancellationToken)
        .ForEachAsync(value => { Debug.Log("Toggle 值变化:" + value); });
}

示例七:监听 Slider 值变化

类似于 Toggle,OnSliderValueChangedAsync 方法通过异步流监听 Slider 数值变化,每次变化都输出当前值,方便对滑动条数值的动态监控。

private async UniTaskVoid OnSliderValueChangedAsync(CancellationToken cancellationToken)
{
    await slider.OnValueChangedAsAsyncEnumerable(cancellationToken)
        .ForEachAsync(value => { Debug.Log("Slider 当前值:" + value); });
}

总结

UniTask 赋予了我们强大的异步处理能力,通过本文的示例,我们可以看到如何高效地监听和处理 UI 组件的各种事件。无论是针对按钮的单次点击、持续监听、双击判断,还是利用异步流实时捕获输入框、Toggle 与 Slider 的变化,都充分展现了 UniTask 在简化代码逻辑、提升运行性能方面的优势。

UniTask 在 UI 事件处理中的核心优势:

  1. 无阻塞异步操作
    利用 async/await 机制,确保 UI 事件处理在后台进行,不会阻塞主线程,从而保障流畅的用户体验。

  2. 轻量高效的实现
    采用结构体和对象池的设计,大幅降低垃圾回收压力,使得高频事件处理更加稳定。

  3. 灵活的事件调度
    结合 CancellationToken 和异步 LINQ,不仅能够精细控制事件处理流程,还能轻松应对复杂的交互逻辑。

最佳实践提示:

  • 在组件销毁时,务必使用 GetCancellationTokenOnDestroy() 来管理异步任务,防止潜在的内存泄露。
  • 对于频繁变化的 UI 事件(如 Slider 滑动),优先采用异步流 (AsAsyncEnumerable) 方式进行监听,确保数据更新高效稳定。
  • 当存在多重事件逻辑或需要顺序处理时,可通过 Queue() 方法对事件进行排队,保证每个事件都能得到妥善处理。

总之,合理运用 UniTask 的异步处理策略不仅能够显著提升代码的可读性和可维护性,更能在高交互的应用场景中带来更佳的性能表现和用户体验。通过本文提供的方案,开发者可以轻松应对复杂的 UI 事件逻辑,实现更优质的应用开发。


12.2 知识点代码

Lesson12_UI监听.cs

using System;
using Cysharp.Threading.Tasks;
using System.Threading;
using UnityEngine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks.Linq; // 引入异步 LINQ 支持

// 注释说明:若要注册事件并使用异步的 lambda,请勿使用 async void,
// 可使用 UniTask.Action 或 UniTask.UnityAction 通过 async UniTaskVoid lambda 创建委托。
// 示例:
// UniTask.Action(
//     async () =>
//     {
//         Debug.Log("aa");
//         await UniTask.Delay(1000);
//     }
// );

// 注释说明:按钮点击事件可通过 OnClickAsync 转换为异步事件,其他 UI 组件类似。
// UniTask 提供了 GetCancellationTokenOnDestroy() 方法用于管理生命周期。
public class Lesson12_UI监听 : MonoBehaviour
{
    public Button btn1;
    public Button btn2;
    public Button btn3;
    public Button btn4;
    public InputField inputField;
    public Toggle toggle; // 新增 Toggle 组件
    public Slider slider; // 新增 Slider 组件

    void Start()
    {
        // 示例一:启动对 btn1 的不同监听方式
        // 只能响应一次点击
        OnClickBtn1AwaitOne().Forget();
        // 持续监听点击事件
        OnClickBtn1AwaitMore(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例二:对 btn2 采用不同的监听和处理方式监听按钮点击间隔 判断是单击还是双击
        OnClickBtn2UniTask(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例三:使用异步 LINQ 监听 btn3 三次点击 只会监听一次三连点击
        OnClickBtn3TripleClick(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例四:使用事件排队处理 btn4 点击事件
        OnClickBtn4QueueEvents(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例五:监听输入框结束编辑事件
        OnInputFieldEndEdit(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例六:监听 Toggle 值变化(异步流,实时输出变化值)
        OnToggleValueChangedAsync(this.GetCancellationTokenOnDestroy()).Forget();

        // 示例七:监听 Slider 值变化(异步流,每次变化输出当前值)
        OnSliderValueChangedAsync(this.GetCancellationTokenOnDestroy()).Forget();
    }

    /// <summary>
    /// 该方法监听按钮的点击事件,但只能响应一次点击。
    /// 因为 await 语句只会执行一次,之后不会再监听点击事件。
    /// </summary>
    private async UniTaskVoid OnClickBtn1AwaitOne()
    {
        // 等待 btn1 被点击
        await btn1.OnClickAsync();
        Debug.Log("OnClickBtn1AwaitOne 再次点击无效:" + Time.time);
    }

    /// <summary>
    /// 该方法可以持续监听按钮的点击事件。
    /// 每次按钮被点击时,都会输出当前的时间。
    /// </summary>
    /// <param name="cancellationToken">用于取消异步操作的 CancellationToken,可通过 GetCancellationTokenOnDestroy 方法获取。</param>
    private async UniTaskVoid OnClickBtn1AwaitMore(CancellationToken cancellationToken)
    {
        // 进入无限循环,持续监听按钮点击事件
        while (true)
        {
            // 获取 btn1 点击事件的异步任务,传入取消令牌
            var btnUniTask = btn1.OnClickAsync(cancellationToken);

            // 等待 btn1 点击事件完成
            await btnUniTask;

            // 按钮点击后,输出日志显示点击时间
            Debug.Log("OnClickBtn1AwaitMore:" + Time.time);
        }
    }

    /// <summary>
    /// 该方法使用 UniTask 处理 btn2 的点击事件,判断是单击还是双击。
    /// </summary>
    /// <param name="cancellationToken"></param>
    private async UniTaskVoid OnClickBtn2UniTask(CancellationToken cancellationToken)
    {
        // 进入无限循环,持续处理 btn2 的点击事件
        while (true)
        {
            // 获取 btn2 第一次点击事件的异步任务
            var firstClickUniTask = btn2.OnClickAsync(cancellationToken);
            // 等待 btn2 第一次点击事件完成
            await firstClickUniTask;
            // 输出第一次点击的日志信息
            Debug.Log("OnClickBtn2UniTask 第1次点击");

            // 获取 btn2 第二次点击事件的异步任务
            var secondClickUniTask = btn2.OnClickAsync(cancellationToken);
            // 判断是单击还是双击,即判断指定时间内是否又点击了,也就是判断第二次点击和等待 1 秒这两个任务发生的先后顺序
            int index = await UniTask.WhenAny(secondClickUniTask,
                UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cancellationToken));

            // 根据 index 判断是第二次点击先发生还是等待 1 秒先完成
            if (index == 0)
            {
                // 若 index 为 0,说明第二次点击先发生,时间间隔不超过 1 秒
                Debug.Log("OnClickBtn2UniTask 时间间隔不超过1");
            }
            else
            {
                // 若 index 不为 0,说明等待 1 秒先完成,时间间隔超过 1 秒
                Debug.Log("OnClickBtn2UniTask 时间间隔超过1");
            }
        }
    }

    /// <summary>
    /// 该方法使用异步 LINQ 监听 btn3 三次点击。
    /// 注意:该方法只会监听一次三连点击,不会持续监听。
    /// 如果需要持续监听,需要自己加while
    /// </summary>
    /// <param name="cancellationToken"></param>
    private async UniTaskVoid OnClickBtn3TripleClick(CancellationToken cancellationToken)
    {
        // 使用异步 LINQ 等待 btn3 被点击三次
        // await btn3.OnClickAsAsyncEnumerable().Take(3).LastAsync(cancellationToken);
        await btn3.OnClickAsAsyncEnumerable().Take(3)
            .ForEachAsync(_ => { Debug.Log("OnClickBtn3TripleClick: 每次点击触发"); }, cancellationToken);

        // // index从0开始 第一次点击index会是0 所以取到的是0 1 2 index为2时 也就是第三次点击 所以会输出三次点击完成
        // var asyncEnumerable = btn3.OnClickAsAsyncEnumerable();
        // await asyncEnumerable.Take(3).ForEachAsync
        // ((_, index) =>
        // {
        //     if (cancellationToken.IsCancellationRequested) return;
        //
        //     if (index == 0)
        //     {
        //         Debug.Log(0);
        //     }
        //     else if (index == 1)
        //     {
        //         Debug.Log(1);
        //     }
        //     else
        //     {
        //         Debug.Log(2);
        //     }
        // }, cancellationToken);

        Debug.Log("OnClickBtn3TripleClick: 三次点击完成");
    }

    /// <summary>
    /// 该方法使用事件排队处理 btn4 点击事件。
    /// </summary>
    /// <param name="cancellationToken"></param>
    private async UniTaskVoid OnClickBtn4QueueEvents(CancellationToken cancellationToken)
    {
        // 对 btn4 的点击事件进行排队处理
        // 每次点击事件都会被添加到队列中,然后依次处理
        // 比如如下示例中 要等三秒才能处理下一个点击事件
        // 处理完成后,队列中的事件会被移除
        int count = 0;
        await btn4.OnClickAsAsyncEnumerable().Queue().ForEachAwaitAsync(async _ =>
        {
            Debug.Log($"OnClickBtn4QueueEvents: 开始处理点击事件{count}");
            await UniTask.Delay(TimeSpan.FromSeconds(3), cancellationToken: cancellationToken);
            Debug.Log($"OnClickBtn4QueueEvents: 点击事件{count}处理完成");
            count++;
        }, cancellationToken);
    }

    /// <summary>
    /// 该方法监听输入框结束编辑事件。
    /// </summary>
    /// <param name="cancellationToken"></param>
    private async UniTaskVoid OnInputFieldEndEdit(CancellationToken cancellationToken)
    {
        // 监听输入框结束编辑事件
        await foreach (var text in inputField.OnEndEditAsAsyncEnumerable().WithCancellation(cancellationToken))
        {
            Debug.Log($"OnInputFieldEndEdit: 输入框结束编辑,输入内容为: {text}");
        }
    }

    /// <summary>
    /// 示例六:监听 Toggle 的值变化事件,并在每次变化时输出当前值
    /// </summary>
    private async UniTaskVoid OnToggleValueChangedAsync(CancellationToken cancellationToken)
    {
        await toggle.OnValueChangedAsAsyncEnumerable(cancellationToken)
            .ForEachAsync(value => { Debug.Log("Toggle 值变化:" + value); });
    }

    /// <summary>
    /// 示例七:监听 Slider 的值变化事件,并在每次变化时输出当前值
    /// </summary>
    private async UniTaskVoid OnSliderValueChangedAsync(CancellationToken cancellationToken)
    {
        await slider.OnValueChangedAsAsyncEnumerable(cancellationToken)
            .ForEachAsync(value => { Debug.Log("Slider 当前值:" + value); });
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏