UniTask 异步任务

文章目录

  • 前言
  • 一、UniTask是什么?
  • 二、使用步骤
  • 三、常用的UniTask API和示例
    • 1.编写异步方法
    • 2.处理异常
    • 3.延迟执行
    • 4.等待多个UniTask或者一个UniTas完成
    • 5.异步加载资源示例
    • 6.手动控制UniTask的完成状态
    • 7.UniTask.Lazy延迟任务的创建
    • 8.后台线程切换Unity主线程
    • 9.不要返回值
    • 10.缓存UniTask的结果
    • 11.指定异步操作阶段执行
    • 12.创建完成的UniTask
    • 13.UniTask.ToCoroutine转换协程
    • 14.异步迭代集合
    • 15. 异步判断
    • 16. uniTask的取消
    • 17.网络请求加载图片
    • 18.异步判断按钮是否被双击
    • 19.每次点击修改按钮不同的文本
  • 四、 总结

前言

随着Unity游戏开发的流行,异步编程变得越来越重要。UniTask是一个轻量级的异步编程库,它为Unity开发者提供了更高效的编程方式。本文将介绍UniTask的基础内容和一些常用的API,以及它们的使用示例。


一、UniTask是什么?

UniTask是一个专为Unity设计的异步编程库,它提供了类似于C#的Taskasync/await的功能,但是更加适合Unity的执行模型和生命周期。

二、使用步骤

UniTaskGit地址
UniTask中文文档地址

首先,需要在Unity项目中安装UniTask。可以通过Unity Package Manager(UPM)安装,或者直接从GitHub下载源码

本文介绍从GitHub下载
在这里插入图片描述

在这里插入图片描述


三、常用的UniTask API和示例

1.编写异步方法

使用UniTask时,可以像编写普通的异步方法一样使用async关键字和UniTask返回类型

// 示例:一个简单的异步加载场景的方法
async UniTask LoadSceneAsync(string sceneName)
{// 使用UniTask的场景加载方法await SceneManager.LoadSceneAsync(sceneName).ToUniTask();// 场景加载完成后的操作Debug.Log("Scene loaded");
}

2.处理异常

UniTask也支持异常处理,可以使用try/catch块来捕获异步方法中的异常

// 示例:带有异常处理的异步方法
async UniTask DoSomethingAsync()
{try{// 可能会抛出异常的操作await SomeRiskyOperation().ToUniTask();}catch (Exception ex){// 处理异常Debug.LogError(ex.Message);}
}

3.延迟执行

UniTask.Delay: 延迟执行,类似于Task.Delay

// 延迟执行示例
async UniTask DelayedOperation()
{await UniTask.Delay(TimeSpan.FromSeconds(5));Debug.Log("Operation executed after 5 seconds");
}

4.等待多个UniTask或者一个UniTas完成

UniTask.WhenAll: 等待多个UniTask完成,类似于Task.WhenAll

// 并行执行多个任务示例
async UniTask RunMultipleTasks()
{// 创建多个任务var task1 = DoTask1Async();var task2 = DoTask2Async();// 等待所有任务完成await UniTask.WhenAll(task1, task2);Debug.Log("全部任务完成");
}
async void RunSingleTask()
{UniTask task1 = UniTask.WaitUntil(() => isClick1);UniTask task2 = UniTask.WaitUntil(() => isClick2);await UniTask.WhenAny(task1, task2);Debug.Log("一个任务完成");
}

5.异步加载资源示例

// 异步加载资源示例
async UniTask<Texture> LoadTextureAsync(string url)
{using (var request = UnityWebRequestTexture.GetTexture(url)){await request.SendWebRequest().ToUniTask();if (request.isNetworkError || request.isHttpError){Debug.LogError(request.error);return null;}return DownloadHandlerTexture.GetContent(request);}
}

6.手动控制UniTask的完成状态

UniTaskCompletionSource允许你手动控制UniTask的完成状态。这在需要等待非异步方法完成的情况下非常有用。

UniTaskCompletionSource<bool> ucs = new UniTaskCompletionSource<bool>();// 在某个事件发生时完成任务
void OnSomeEvent()
{ucs.TrySetResult(true);
}// 等待事件完成
async UniTask WaitSomeEventAsync()
{await ucs.Task;Debug.Log("Event occurred");
}

7.UniTask.Lazy延迟任务的创建

UniTask.Lazy可以延迟任务的创建,直到真正需要执行任务时才会创建。

// 示例:延迟创建任务
UniTask<string> lazyTask = UniTask.Lazy(async () =>
{await UniTask.Delay(1000);return "Result after delay";
});// 在需要结果时等待任务
string result = await lazyTask;
Debug.Log(result);

8.后台线程切换Unity主线程

在需要从后台线程切换回Unity主线程时,可以使用UniTask.SwitchToMainThread

// 示例:在后台线程上执行操作,然后切换回主线程
async UniTask DoOperationAndSwitchBack()
{// 在后台线程上执行耗时操作await UniTask.Run(() => SomeHeavyOperation());// 切换回主线程await UniTask.SwitchToMainThread();// 在主线程上执行Unity相关操作Debug.Log("Back on main thread");
}

9.不要返回值

当你不需要关心异步方法的返回值时,可以使用UniTaskVoid。这对于触发事件或执行不需要返回结果的后台操作非常有用。

// 示例:一个不返回任何结果的异步方法
async UniTaskVoid PerformBackgroundOperation()
{// 执行一些后台操作await UniTask.Delay(1000);Debug.Log("Background operation completed");
}

10.缓存UniTask的结果

如果你想要缓存一个UniTask的结果以供后续使用,可以使用UniTask<T>.Preserve方法。

// 示例:缓存异步操作的结果
UniTask<int> originalTask = CalculateValueAsync();
UniTask<int> preservedTask = originalTask.Preserve();// 在不同的地方使用缓存的结果
int result1 = await preservedTask;
int result2 = await preservedTask;

11.指定异步操作阶段执行

PlayerLoopTiming枚举允许你指定异步操作应该在Unity的哪个阶段执行。这可以帮助你更精确地控制代码的执行时间。

// 示例:在FixedUpdate阶段执行异步操作
async UniTask PerformOperationInFixedUpdate()
{await UniTask.Yield(PlayerLoopTiming.FixedUpdate);// 在FixedUpdate阶段执行的代码Debug.Log("This is executed in FixedUpdate");
}

12.创建完成的UniTask

当你已经有了结果,并且想要创建一个已经完成的UniTask时,可以使用UniTask.FromResult

// 示例:创建一个已经完成的UniTask
UniTask<int> completedTask = UniTask.FromResult(42);

13.UniTask.ToCoroutine转换协程

如果你需要将UniTask与旧的协程系统兼容,可以使用UniTask.ToCoroutine将其转换为协程。

// 示例:将UniTask转换为协程
IEnumerator MyCoroutine()
{yield return LoadSceneAsync("MyScene").ToCoroutine();
}

14.异步迭代集合

UniTask支持异步枚举器,这允许你使用await foreach来异步迭代集合。

// 示例:使用异步枚举器迭代集合
async UniTask ProcessItemsAsync(IAsyncEnumerable<int> items)
{await foreach (var item in items){Debug.Log(item);}
}

15. 异步判断

UniTask.WaitUntilUniTask.WaitWhile这些方法允许你等待直到某个条件为真或为假。

// 示例:等待直到条件为真
async UniTask WaitUntilConditionMet()
{await UniTask.WaitUntil(() => someCondition);Debug.Log("Condition met");
}// 示例:等待直到条件为假
async UniTask WaitWhileConditionMet()
{await UniTask.WaitWhile(() => someCondition);Debug.Log("Condition no longer met");
}

16. uniTask的取消

通过 CancellationTokenSource完成UniTask的取消


public class Test : MonoBehaviour
{private CancellationTokenSource cts;void Start(){cts = new CancellationTokenSource();StartCount();cts.CancelAfter(TimeSpan.FromSeconds(10));}private async UniTask<int> Count(int count, CancellationToken token){for (int i = 0; i < count; i++){Debug.Log(i);await UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: token);}return 0;}private async void StartCount(){try{await Count(100, cts.Token);}catch (OperationCanceledException){Debug.Log("计数取消");}}
}

17.网络请求加载图片

private async UniTaskVoid UnityTaskTest()
{var webRequest = UnityWebRequestTexture.GetTexture(url);var result = await webRequest.SendWebRequest();var texture = ((DownloadHandlerTexture)webRequest.downloadHandler).texture;Sprite sprite = Sprite.Create(texture,new Rect(Vector2.zero, new Vector2(texture.width, texture.height)), new Vector2(0.5f, 0.5f));image2.sprite = sprite;}

18.异步判断按钮是否被双击

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;public class Test : MonoBehaviour
{public Button btn1;void Start(){CheckClickInternal(this.GetCancellationTokenOnDestroy(), 1).Forget();}/// <summary>/// 异步判断按钮是否被双击/// </summary>/// <param name="token"></param>private async UniTaskVoid CheckClickInternal(CancellationToken token, float time){while (true){var firstClick = btn1.OnClickAsync(token);await firstClick;var secondClick = btn1.OnClickAsync(token);//判断第二次点击和等待time时间谁先执行,如果是secondClick返回0,如果不是返回1int index = await UniTask.WhenAny(secondClick,UniTask.Delay(TimeSpan.FromSeconds(time), cancellationToken: token));if (index == 0){Debug.Log("被双击了");}}}
}

19.每次点击修改按钮不同的文本

using System.Collections;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.Linq;
using UnityEngine;
using UnityEngine.UI;public class Test : MonoBehaviour
{public Button btn1;// Start is called before the first frame updatevoid Start(){btn1.GetComponentInChildren<Text>().text = "杀";ChangeBtnTextClick(this.GetCancellationTokenOnDestroy()).Forget();}/// <summary>/// 每次点击修改按钮不同的文本;/// </summary>/// <param name="token"></param>async UniTask ChangeBtnTextClick(CancellationToken token){var click = btn1.OnClickAsAsyncEnumerable();await click.Take(3).ForEachAsync((_, index) =>{if (token.IsCancellationRequested) return;btn1.GetComponentInChildren<Text>().text = index switch{0 => "再杀",1 => "再补一刀",_ => ""};}, cancellationToken: token);btn1.GetComponentInChildren<Text>().text = "结束";}
}

四、 总结

Unitask 是一个优秀的异步任务库,它简化了在 Unity 中处理异步操作的方式,提高了开发效率和代码可维护性。通过本文的介绍,可以更加深入地了解 Unitask 的使用方法,并在自己的项目中应用它,从而提升游戏开发的质量和效率。

在使用 Unitask 时,需要注意以下几点:

​ 不要在 Update 方法中使用 async/await,因为 Unity 主线程是单线程的,使用异步方法可能导致性能问题。

​ 尽量避免过多的异步嵌套,以免导致代码复杂度过高。

​ 使用 try/catch 来处理异步操作中的错误,确保程序的稳定性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/282164.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣爆刷第102天之hot100五连刷96-100

力扣爆刷第102天之hot100五连刷96-100 文章目录 力扣爆刷第102天之hot100五连刷96-100一、136. 只出现一次的数字二、169. 多数元素三、75. 颜色分类四、31. 下一个排列五、287. 寻找重复数 一、136. 只出现一次的数字 题目链接&#xff1a;https://leetcode.cn/problems/sing…

C语言字符函数与字符串函数:编织文字的舞会之梦(下)

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看&#xff0c;已成习惯 创作不易&#xff0c;多多支持&#xff01; 目录 七、strncpy的使用以及模拟实现 八、strncat的使用以及模拟实现 九、strncmp的使用以及模拟实现 十、strstr的使用以及模拟…

设计模式之抽象工厂模式解析

抽象工厂模式 1&#xff09;问题 工厂方法模式中的每个工厂只生产一类产品&#xff0c;会导致系统中存在大量的工厂类&#xff0c;增加系统的开销。 2&#xff09;概述 a&#xff09;产品族 和 产品等级结构 产品等级结构&#xff1a;产品的继承结构&#xff1b; 产品族&…

华为ensp中ospf基础 原理及配置命令(详解)

CSDN 成就一亿技术人&#xff01; 作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; CSDN 成就一亿技术人&#xff01; ————前言———— OSPF 的全称是 Open Shortest Path First&#xff0c;意为“开放式最短路径优先”。是一种内部网关协…

银行OA系统|基于SpringBoot架构+ Mysql+Java+ B/S结构的银行OA系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

Occupancy 训练策略

损失函数 Dice Loss Dice Loss 是一种用于图像分割的损失函数&#xff0c;其灵感来自于Dice 系数&#xff0c;是一种衡量两个样本相似度的方法。Dice 系数定义为&#xff1a; Dice 系数 2 * TP / (2 * TP FP FN) 其中&#xff1a; TP&#xff1a;预测为正且真实值为正的像…

网易有道 3/22

一面还比较常规&#xff0c;二面真的是压力爆炸&#xff0c;还是感觉自己太菜了 一面计网部分直接就是垮了&#xff0c;二面的话面试官水平很高&#xff0c;根本就和我不是一个级别的&#xff0c;三言两语就知道了我的项目大致情况&#xff0c;然后不断拷打 项目问完了又问了…

OpenGL学习笔记【3】—— GLAD配置

一、为什么用GLAD 由于OpenGL驱动版本众多&#xff0c;它大多数函数的位置都无法在编译时确定下来&#xff0c;需要在运行时查询。所以任务就落在了开发者身上&#xff0c;开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用。取得地址的方法因平台而异&…

超声波清洗机是用来干什么的?好用眼镜超声波清洗机不能错过

在快节奏的现代生活中&#xff0c;每一项提高效率和清洁效果的技术都值得我们关注。超声波清洗机就是这样一种技术的完美体现&#xff0c;它通过高频声波在液体中产生微小的气泡&#xff0c;这些气泡在压力作用下迅速爆炸&#xff0c;产生的强大冲击力能够深入物品的微小缝隙&a…

阿里云权益中心2024年五大上云优惠权益解析,助力用户优惠上云

上云首选&#xff0c;普惠好价&#xff0c;2024年阿里云通过权益中心为个人和企业用户提供五大上云优惠权益&#xff0c;为开发者和企业提供多款新老同享、续费同价产品&#xff1b;超150款免费试用产品&#xff1b;初创企业最高可得最低3500元&#xff0c;最高100万上云抵扣金…

Docker 安装 Skywalking以及UI界面

关于Skywalking 在现代分布式系统架构中&#xff0c;应用性能监控&#xff08;Application Performance Monitoring, APM&#xff09;扮演着至关重要的角色。本文将聚焦于一款备受瞩目的开源APM工具——Apache Skywalking&#xff0c;通过对其功能特性和工作原理的详细介绍&am…

Unity UGUI之Toggle基本了解

在Unity中&#xff0c;Toggle一般用于两种状态之间的切换&#xff0c;通常用于开关或复选框等功能。 它的基本属性如图&#xff1a; 其中&#xff0c; Interactable&#xff08;可交互&#xff09;&#xff1a;指示Toggle是否可以与用户交互。设置为false时&#xff0c;禁用To…

Leetcode 70.爬楼梯

心路历程&#xff1a; 这道题是之前学院的一道复试题&#xff0c;大家都没怎么刷过算法题&#xff0c;只记得当年凭借几次试错自己把这道题做出来了&#xff0c;当时也不知道动态规划之类的。 正常来讲&#xff0c;这种找不到循环结构的题一般都是递归解决。 注意的点&#x…

Java语法学习八之认识String类

String类的重要性 在C语言中已经涉及到字符串了&#xff0c;但是在C语言中要表示字符串只能使用字符数组或者字符指针&#xff0c;可以使用标准库提供的字符串系列函数完成大部分操作&#xff0c;但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想&#xff0c;而…

使用 Pytorch 和 Rasterio 的自定义地理空间数据加载器

地理空间数据在从遥感和城市规划到环境监测和灾害管理的各个领域发挥着至关重要的作用。在处理机器学习任务的地理空间数据时,准备自定义数据加载器对于有效加载、预处理和增强数据而不丢失其属性至关重要,特别是当输入图像具有超过 3 个波段时。 Rasterio确实是一个专门为有…

【嵌入式——QT】QT Charts

【嵌入式——QT】QT Charts 概述Qt提供的坐标轴类QChartQLineSeriesQValueAxis常见图表及用到的序列类图示代码示例 概述 QT Charts模块是一组易于使用的图表组件&#xff0c;它基于Qt的Graphics View架构&#xff0c;其核心组件是QChartView和QChart&#xff0c;QChartView父…

软硬件全开源,方案分享 | 旋钮温控器方案

温控器用于控制室内暖通设备&#xff0c;通过暖通设备为室内环境提供冷源和热源&#xff0c;从而调节室内温度环境&#xff0c;为人们提供舒适的生活环境。 旋钮式温控器更为结构简洁、操作简便&#xff0c;降低了用户的使用难度&#xff0c;提供智能化的控制方法&#xff0c;…

基于时空上下文(STC)的运动目标跟踪算法,Matlab实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

java面试:常见的限流算法有哪些

1 什么是限流算法 限流算法是一种用于限制流量请求的频率或速率的算法&#xff0c;其目的是在高并发或大流量请求的情况下&#xff0c;保护系统服务的安全性和可用性。限流算法可以应对热点业务带来的突发请求、调用方bug导致的突发请求以及恶意攻击请求等情况。是一种系统保护…

使用 ONLYOFFICE API 构建 Java 转换器,在 Word 和 PDF 之间进行转换

文章作者&#xff1a;ajun 随着文档处理需求的增加&#xff0c;格式转换成为了一个重要的需求点。由于PDF格式具有跨平台、不易被篡改的特性&#xff0c;将Word格式(.docx)转换为PDF格式(.pdf)的需求尤为强烈。ONLYOFFICE作为一个强大的办公套件&#xff0c;提供了这样的转换功…