7.UniTask与协程转换

7.UniTask与协程转换


7.1 知识点

UniTask 与协程转换详解

在 Unity 开发中,协程一直是处理异步逻辑的常用方式。随着 UniTask 的出现,我们可以更高效地使用异步/等待语法,同时也可以方便地实现 UniTask 与协程之间的互相转换。本文将通过具体示例,介绍如何直接 await 协程、将 UniTask 转换为协程以及将协程转换为 UniTask。

直接 Await 协程

在示例中,我们可以直接 await 一个协程方法来等待其完成。通过这种方式,不仅能够利用 UniTask 的语法糖简化代码,还能在异步方法中直接处理协程的结果。

// 示例一:直接 await 协程并等待其完成
IEnumerator CoroutineTest()
{
    Debug.Log($"协程开始,当前时间: {Time.time}");
    // 等待 1 秒
    yield return new WaitForSeconds(1);
    Debug.Log($"协程结束,当前时间: {Time.time}");
}

async void Start()
{
    // 直接 await 协程
    await CoroutineTest();
}

通过 await 协程,我们可以方便地将传统协程嵌入到异步方法中,无需担心协程的调度问题。

将 UniTask 转换为协程

有时我们可能需要在传统协程中调用 UniTask 提供的功能。UniTask 提供了 ToCoroutine 扩展方法,可以将一个 UniTask 转换为协程,从而方便地在 StartCoroutine 中使用。

// 示例二:将 UniTask 转换为协程并等待
IEnumerator UniTaskToCoroutineTest()
{
    Debug.Log($"UniTask 转换为协程开始,当前时间: {Time.time}");
    // 将 UniTask 延迟 1 秒转换为协程并等待
    yield return UniTask.Delay(TimeSpan.FromSeconds(1)).ToCoroutine();
    Debug.Log($"UniTask 转换为协程结束,当前时间: {Time.time}");
}

void Start()
{
    StartCoroutine(UniTaskToCoroutineTest());
}

这种转换方式允许开发者在协程环境中依然享受到 UniTask 高效的异步操作。

将协程转换为 UniTask

同样地,如果希望在 UniTask 异步方法中使用已有的协程逻辑,可以将协程转换为 UniTask。通过 ToUniTask 扩展方法,我们可以方便地将协程转换为 UniTask,并通过 await 等待其完成。

// 示例三:将协程转换为 UniTask 并等待
async UniTask CoroutineToUniTaskTest()
{
    Debug.Log($"协程转换为 UniTask 开始,当前时间: {Time.time}");
    // 创建一个协程实例
    IEnumerator coroutine = CoroutineTest();
    // 将协程转换为 UniTask 并等待
    await coroutine.ToUniTask(this);
    Debug.Log($"协程转换为 UniTask 结束,当前时间: {Time.time}");
}

async void Start()
{
    await CoroutineToUniTaskTest();
}

这种转换方式让我们可以在统一的异步方法中混合使用协程和 UniTask,充分利用各自的优势,从而使代码结构更清晰。

进行测试

using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using UnityEngine;

public class Lesson07_UniTask与协程转换 : MonoBehaviour
{
    async void Start()
    {
        // 示例一:直接await协程(Coroutine)并等待其完成
        // StartCoroutine(CoroutineTest());
        await CoroutineTest();

        // 示例二:将 UniTask 转换为协程并等待
        StartCoroutine(UniTaskToCoroutineTest());

        // 示例三:将协程转换为 UniTask 并等待
        await CoroutineToUniTaskTest();
    }

    /// <summary>
    /// 示例一:直接await协程(Coroutine)并等待其完成
    /// </summary>
    IEnumerator CoroutineTest()
    {
        Debug.Log($"协程开始,当前时间: {Time.time}");
        // 等待 1 秒
        yield return new WaitForSeconds(1);
        Debug.Log($"协程结束,当前时间: {Time.time}");
    }

    /// <summary>
    /// 示例二:将 UniTask 转换为协程并等待
    /// </summary>
    IEnumerator UniTaskToCoroutineTest()
    {
        Debug.Log($"UniTask 转换为协程开始,当前时间: {Time.time}");
        // 将 UniTask 延迟 1 秒转换为协程并等待
        yield return UniTask.Delay(TimeSpan.FromSeconds(1)).ToCoroutine();
        Debug.Log($"UniTask 转换为协程结束,当前时间: {Time.time}");
    }

    /// <summary>
    /// 示例三:将协程转换为 UniTask并等待
    /// </summary>
    async UniTask CoroutineToUniTaskTest()
    {
        Debug.Log($"协程转换为 UniTask 开始,当前时间: {Time.time}");
        // 创建一个协程
        IEnumerator coroutine = CoroutineTest();
        // 将协程转换为 UniTask 并等待
        await coroutine.ToUniTask(this);
        Debug.Log($"协程转换为 UniTask 结束,当前时间: {Time.time}");
    }
}

总结

本文详细介绍了 UniTask 与协程之间的互相转换:

  • 直接 await 协程:让传统协程直接融入 async/await 流程中。
  • 将 UniTask 转换为协程:利用 ToCoroutine 方法在传统协程环境中使用 UniTask 功能。
  • 将协程转换为 UniTask:通过 ToUniTask 方法将协程嵌入到 UniTask 异步流程中。

通过这些方式,开发者可以灵活选择合适的异步编程模式,从而提高项目开发效率和代码可读性。


7.2 知识点代码

Lesson07_UniTask与协程转换.cs

using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using UnityEngine;

public class Lesson07_UniTask与协程转换 : MonoBehaviour
{
    async void Start()
    {
        // 示例一:直接await协程(Coroutine)并等待其完成
        // StartCoroutine(CoroutineTest());
        await CoroutineTest();

        // 示例二:将 UniTask 转换为协程并等待
        StartCoroutine(UniTaskToCoroutineTest());

        // 示例三:将协程转换为 UniTask 并等待
        await CoroutineToUniTaskTest();
    }

    /// <summary>
    /// 示例一:直接await协程(Coroutine)并等待其完成
    /// </summary>
    IEnumerator CoroutineTest()
    {
        Debug.Log($"协程开始,当前时间: {Time.time}");
        // 等待 1 秒
        yield return new WaitForSeconds(1);
        Debug.Log($"协程结束,当前时间: {Time.time}");
    }

    /// <summary>
    /// 示例二:将 UniTask 转换为协程并等待
    /// </summary>
    IEnumerator UniTaskToCoroutineTest()
    {
        Debug.Log($"UniTask 转换为协程开始,当前时间: {Time.time}");
        // 将 UniTask 延迟 1 秒转换为协程并等待
        yield return UniTask.Delay(TimeSpan.FromSeconds(1)).ToCoroutine();
        Debug.Log($"UniTask 转换为协程结束,当前时间: {Time.time}");
    }

    /// <summary>
    /// 示例三:将协程转换为 UniTask并等待
    /// </summary>
    async UniTask CoroutineToUniTaskTest()
    {
        Debug.Log($"协程转换为 UniTask 开始,当前时间: {Time.time}");
        // 创建一个协程
        IEnumerator coroutine = CoroutineTest();
        // 将协程转换为 UniTask 并等待
        await coroutine.ToUniTask(this);
        Debug.Log($"协程转换为 UniTask 结束,当前时间: {Time.time}");
    }
}


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

×

喜欢就点赞,疼爱就打赏