unity开发学会UniTask,告别非人性回调写法

2024-01-06 20:44

本文主要是介绍unity开发学会UniTask,告别非人性回调写法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 简介
  • Unitask 的常见用法
  • 基础使用案例:
    • 示例1:并发执行多个任务并等待全部完成
    • 示例2:取消正在进行的任务
    • 示例3:结合Update循环使用UniTask
    • 示例4:并发加载多个资源并在完成后显示

简介

Unity 的 UniTask 是一种用于异步编程的 C# 库,它扩展了 .NET 中的 Task 和 await/async 模式。

  1. 与传统的 Task 和 async/await 模式相比,UniTask 更加轻量级,因为它不需要像 Task 一样创建和管理线程池。
  2. UniTask 具有更高的性能,因为它使用了更少的内存和 CPU 资源,几乎0GC消耗。
  3. UniTask 还提供了更多的功能,如取消和超时等功能,这些功能在传统的 Task 中并不容易实现。

Unitask 的常见用法

1、异步等待:使用 await 关键字,可以等待一个异步操作完成,这样就不需要手动处理回调或使用协程。
2、延迟执行:使用 UniTask.Delay 方法可以在指定的时间后执行一个操作,而不需要使用协程或计时器。
3、同步化操作:使用 UniTask.SwitchToMainThread 方法可以在主线程上执行一个操作,这对于访问 Unity 的组件或 API 非常有用。
4、迭代器:使用 UniTask.ToCoroutine 方法可以将一个 UniTask 对象转换为 IEnumerator,从而可以在协程中使用。
5、任务链:使用 UniTask.WhenAll 或 UniTask.WhenAny 方法可以创建一个任务链,等待多个异步操作完成后执行下一步操作。
6、取消任务:使用 UniTaskCancellationToken 类可以取消异步操作,这对于长时间运行的操作非常有用

基础使用案例:

using Cysharp.Threading.Tasks; // 首先需要引入UniTask库public class UniTaskExample : MonoBehaviour
{async void Start(){// 使用UniTask.Delay进行延迟操作await UniTask.Delay(TimeSpan.FromSeconds(1.0f));Debug.Log("Waited for 1 second.");// 异步加载资源var www = UnityWebRequest.Get("https://example.com/somefile.txt");using (var op = UnityWebRequestAsyncOperation.FromAsync(www.SendWebRequest)){await op.ToUniTask(); // 将UnityWebRequest的异步操作转换为UniTaskif (www.result == UnityWebRequest.Result.Success){string text = www.downloadHandler.text;Debug.Log("Downloaded content: " + text);}else{Debug.LogError($"Failed to download: {www.error}");}}// 异步更新UIawait UniTask.SwitchToMainThread(); // 切换到主线程更新UISomeUIComponent.text = "Updated via UniTask";}
}

在上述示例中:

  1. 我们首先展示了如何使用 UniTask.Delay 来实现延迟操作,与 yield return new WaitForSeconds 相比,这种方式不会阻塞主运行线程。

  2. 然后我们演示了如何结合Unity的 UnityWebRequest 异步下载资源,并将其转换为 UniTask,以便使用 await 关键字来等待请求完成。

  3. 最后展示了如何通过 UniTask.SwitchToMainThread 方法将异步任务的结果应用到主线程上的UI元素上,确保UI更新是安全的。

UniTask还可以用于很多其他场景,比如I/O操作、动画等待、游戏逻辑异步化等,能够极大地简化和优化Unity中的异步编程模型。

当然,UniTask 的功能远不止这些基础使用案例。这里再提供一些进阶用法示例:

示例1:并发执行多个任务并等待全部完成

using System.Collections.Generic;
using Cysharp.Threading.Tasks;public class UniTaskExampleAdvanced : MonoBehaviour
{async void Start(){var tasks = new List<UniTask<string>>(); // 创建一个任务列表来存储异步操作// 并发启动多个下载任务for (int i = 0; i < 5; i++){string url = $"https://example.com/resource{i}.txt";tasks.Add(DownloadTextAsync(url));}// 使用UniTask.WhenAll等待所有任务完成var results = await UniTask.WhenAll(tasks);foreach (var result in results){Debug.Log($"Downloaded text: {result}");}}private async UniTask<string> DownloadTextAsync(string url){var www = UnityWebRequest.Get(url);using (var op = UnityWebRequestAsyncOperation.FromAsync(www.SendWebRequest)){await op.ToUniTask();if (www.result == UnityWebRequest.Result.Success){return www.downloadHandler.text;}else{Debug.LogError($"Failed to download: {www.error}");return null;}}}
}

在这个例子中,我们创建了多个 DownloadTextAsync 异步任务,并使用 UniTask.WhenAll 来等待所有任务都完成。当所有任务完成后,我们可以获取到每个任务的结果。

示例2:取消正在进行的任务

using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;public class UniTaskCancellationExample : MonoBehaviour
{public Button startButton;public Button cancelButton;private CancellationTokenSource cancellationTokenSource;private async void Start(){startButton.onClick.AddListener(async () => await LongRunningTaskAsync());cancelButton.onClick.AddListener(() => CancelLongRunningTask());cancellationTokenSource = new CancellationTokenSource();}private async UniTaskVoid LongRunningTaskAsync(){try{Debug.Log("Starting long running task...");await UniTask.Delay(TimeSpan.FromSeconds(10), cancellationTokenSource.Token);Debug.Log("Long running task completed.");}catch (OperationCanceledException){Debug.LogWarning("Long running task was cancelled.");}}private void CancelLongRunningTask(){cancellationTokenSource.Cancel();}
}

这个示例展示了如何通过传递 CancellationToken 来支持任务的取消。当用户点击“取消”按钮时,我们会调用 cancellationTokenSource.Cancel() 来取消正在运行的长时间任务,如果任务监听到了取消信号,则会抛出 OperationCanceledException 异常,从而可以处理取消逻辑。

示例3:结合Update循环使用UniTask

在Unity中,我们有时需要在Update函数中执行异步操作,并在下一次Update时继续处理。UniTask可以方便地实现这一需求:

using Cysharp.Threading.Tasks;
using UnityEngine;public class UniTaskWithUpdate : MonoBehaviour
{private async UniTaskVoid AsyncProcess(){for (int i = 0; i < 10; i++){Debug.Log($"Processing step {i}...");await UniTask.Yield(); // 暂停当前任务,等待下一个Update周期}Debug.Log("Async process completed.");}private UniTask runningTask;void Update(){if (runningTask.IsCompleted){// 如果上一轮的异步任务已完成,则开始新的任务runningTask = AsyncProcess();runningTask.ToCoroutine(this); // 将UniTask转换为IEnumerator以配合StartCoroutine}}
}

在这个示例中,我们在Update函数中启动并跟踪一个异步任务。通过UniTask.Yield(),我们可以在每个异步步骤之间暂停,等待下一次Update调用。

示例4:并发加载多个资源并在完成后显示

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using Cysharp.Threading.Tasks;public class UniTaskAssetLoadingExample : MonoBehaviour
{public List<GameObject> prefabsToLoad;async void Start(){var tasks = new List<UniTask<GameObject>>();foreach (var prefabPath in prefabsToLoad.Select(p => p.name)){tasks.Add(LoadPrefabAsync(prefabPath));}var loadedPrefabs = await UniTask.WhenAll(tasks);foreach (var loadedPrefab in loadedPrefabs){Instantiate(loadedPrefab, transform);}}private async UniTask<GameObject> LoadPrefabAsync(string prefabPath){var handle = Addressables.LoadAssetAsync<GameObject>(prefabPath);return await handle.Task.AsUniTask(cancellationToken: default);}
}

这个例子展示了如何利用UniTask来并发加载多个资源,并在所有资源加载完毕后一次性进行处理。这里我们使用了Addressables来进行资源加载,通过UniTask.WhenAll等待所有加载任务完成。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

这篇关于unity开发学会UniTask,告别非人性回调写法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/577554

相关文章

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加

Python中对FFmpeg封装开发库FFmpy详解

《Python中对FFmpeg封装开发库FFmpy详解》:本文主要介绍Python中对FFmpeg封装开发库FFmpy,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、FFmpy简介与安装1.1 FFmpy概述1.2 安装方法二、FFmpy核心类与方法2.1 FF

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.

Python使用smtplib库开发一个邮件自动发送工具

《Python使用smtplib库开发一个邮件自动发送工具》在现代软件开发中,自动化邮件发送是一个非常实用的功能,无论是系统通知、营销邮件、还是日常工作报告,Python的smtplib库都能帮助我们... 目录代码实现与知识点解析1. 导入必要的库2. 配置邮件服务器参数3. 创建邮件发送类4. 实现邮件

基于Python开发一个有趣的工作时长计算器

《基于Python开发一个有趣的工作时长计算器》随着远程办公和弹性工作制的兴起,个人及团队对于工作时长的准确统计需求日益增长,本文将使用Python和PyQt5打造一个工作时长计算器,感兴趣的小伙伴可... 目录概述功能介绍界面展示php软件使用步骤说明代码详解1.窗口初始化与布局2.工作时长计算核心逻辑3

mybatis的mapper对应的xml写法及配置详解

《mybatis的mapper对应的xml写法及配置详解》这篇文章给大家介绍mybatis的mapper对应的xml写法及配置详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录前置mapper 对应 XML 基础配置mapper 对应 xml 复杂配置Mapper 中的相

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1

如何基于Python开发一个微信自动化工具

《如何基于Python开发一个微信自动化工具》在当今数字化办公场景中,自动化工具已成为提升工作效率的利器,本文将深入剖析一个基于Python的微信自动化工具开发全过程,有需要的小伙伴可以了解下... 目录概述功能全景1. 核心功能模块2. 特色功能效果展示1. 主界面概览2. 定时任务配置3. 操作日志演示