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