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#的Task和async/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.WaitUntil 和 UniTask.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 来处理异步操作中的错误,确保程序的稳定性。
相关文章:
UniTask 异步任务
文章目录 前言一、UniTask是什么?二、使用步骤三、常用的UniTask API和示例1.编写异步方法2.处理异常3.延迟执行4.等待多个UniTask或者一个UniTas完成5.异步加载资源示例6.手动控制UniTask的完成状态7.UniTask.Lazy延迟任务的创建8.后台线程切换Unity主线程9.不要返…...
【git分支管理策略】如何高效的管理好代码版本
目录 1.分支管理策略 2.我用的分支管理策略 3.一些常见问题 1.分支管理策略 分支管理策略就是一些经过实践后总结出来的可靠的分支管理的办法,让分支之间能科学合理、高效的进行协作,帮助我们在整个开发流程中合理的管理好代码版本。 目前有两套Git…...
css的transition详解
CSS的transition属性是一个简写属性,用于设置四个过渡效果属性,以在元素的状态改变时创建平滑的动画效果。这四个属性分别是: transition-property: 定义应用过渡效果的CSS属性名称。当指定的CSS属性改变时,过渡效果将…...
agent利用知识来做规划:《KnowAgent: Knowledge-Augmented Planning for LLM-Based Agents》笔记
文章目录 简介KnowAgent思路准备知识Action Knowledge的定义Planning Path Generation with Action KnowledgePlanning Path Refinement via Knowledgeable Self-LearningKnowAgent的实验结果 总结参考资料 简介 《KnowAgent: Knowledge-Augmented Planning for LLM-Based Age…...
01 React新建开发环境
https://create-react-app.dev/docs/getting-started npx create-react-app my-appJSX使用表达式嵌入 function App() {const count 100;function getSelfName() {return "SelfName"}return (<div>Hello World!<div>{This is Javascript message~!}&l…...
nginx--解决响应头带Set-Cookie导致的验证失败
解决响应头带Set-Cookie导致的验证失败 前言给nginx.conf 设置Secure配置完成后会发现cookie就不会发生变化了 前言 在用nginx做代理的时候,会发现nginx在访问不同ip请求的时候会带setCookie 导致后端就是放开cookie验证,在访问玩这个链接他更新了cooki…...
InstructGPT的流程介绍
1. Step1:SFT,Supervised Fine-Tuning,有监督微调。顾名思义,它是在有监督(有标注)数据上微调训练得到的。这里的监督数据其实就是输入Prompt,输出相应的回复,只不过这里的回复是人工…...
docker容器下部署hbase并在springboot中通过jdbc连接
我在windows的docker中部署了一个hbase服务,然后用springboot连接到此服务并访问数据。 详情可参考项目中的README.md。项目中提供了用于构建镜像的dockerfile,以及测试代码。 项目连接: https://gitee.com/forgot940629/hbase_phoenix_sprin…...
Qt——智能指针实战
目录 前言正文一、理论介绍1、QPointer2、QScopedPoint3、QSharedPoint4、QWeakPoint 二、实战演练1、QPoint2、QScopedPoint3、QSharedPointa、示例一b、示例二 4、QWeakPoint END、总结的知识与问题 参考 前言 智能指针的使用,对很多程序员来说,都算是…...
Unity Mobile Notifications推送问题
1.在部分机型点击通知弹窗进不去游戏 把这里改成自己的Activity 2.推送的时候没有横幅跟icon红点 主要是第一句话 注册的时候选项可以选择 defaultNotificationChannel new AndroidNotificationChannel(“default_channel”, “Default Channel”, “For Generic notifica…...
C++_回文串
目录 回文子串 最长回文子串 分割回文串 IV 分割回文串 II 最长回文子序列 让字符串成为回文串的最少插入次数 回文子串 647. 回文子串 思路,i j表示改范围内是否为回文串, ②倒着遍历是为了取出dp[i 1][j - 1] ③i j 只有一对,不会重复…...
【阅读论文】When Large Language Models Meet Vector Databases: A Survey
摘要 本调查探讨了大型语言模型(LLM)和向量数据库(VecDB)之间的协同潜力,这是一个新兴但迅速发展的研究领域。随着LLM的广泛应用,出现了许多挑战,包括产生虚构内容、知识过时、商业应用成本高昂…...
兼职副业大揭秘:六个潜力满满的赚钱途径
亲爱的朋友,你对兼职副业充满好奇与期待,这非常好!在此,我将为你分享一些能够助你赚取额外收入的兼职副业建议。以下是六个颇具潜力的兼职副业方向,希望能为你的探索之路提供些许启发。 1,网络调查与市场洞…...
C++ Qt开发:QUdpSocket实现组播通信
Qt 是一个跨平台C图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QUdpSocket组件实现基于UDP的组播通信…...
excel 表中有图片并在筛选特定行时,只显示该行的图片
建议:选中excel 表中某张图片,CtrlA,选中所有图片。再右键,在菜单中选设置对象格式 在属性里按下图设置, 生效之后,筛选某个产品的时候,就不会显示其他的不符合筛选条件的产品的图片了。...
【QA】MySQL多表查询详解
文章目录 前言关系型数据库中数据表之间的关系数据准备数据内容表间关系 基础查询 | 全部查询多表查询分类1 | 连接查询内连接外连接 | 左外连接外连接 | 右外连接自连接 | 自连接自连接 | 联合查询 分类2 | 子查询返回结果分类 | 标量子查询返回结果分类 | 列子查询返回结果分…...
【Entity Framework】 EF三种开发模式
【Entity Framework】 EF三种开发模式 文章目录 【Entity Framework】 EF三种开发模式一、概述二、DataBase First2.1 DataBase First简介2.2 DataBase First应用步骤2.3 DataBase First总结 三、Model First3.1 Model First简介3.2 Model First实现步骤 四、Code First4.1 Cod…...
数据分析---SQL(5)
目录 子查询单行子查询多行子查询视图(View)创建视图使用视图更新视图视图的优缺点存储过程存储过程的创建存储过程的参数存储过程的优缺点可能导致性能问题避免存储过程引入性能问题子查询 子查询是指在一个查询语句中嵌套另一个查询语句,内部的查询语句称为子查询,外部的…...
《剑指 Offer》专项突破版 - 面试题 93 : 最长斐波那契数列(C++ 实现)
题目链接:最长斐波那契数列 题目: 输入一个没有重复数字的单调递增的数组,数组中至少有 3 个数字,请问数组中最长的斐波那契数列的长度是多少?例如,如果输入的数组是 [1, 2, 3, 4, 5, 6, 7, 8]࿰…...
代码随想录算法训练营第五十五天|583. 两个字符串的删除操作、72. 编辑距离
583. 两个字符串的删除操作 刷题https://leetcode.cn/problems/delete-operation-for-two-strings/description/文章讲解https://programmercarl.com/0583.%E4%B8%A4%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E5%88%A0%E9%99%A4%E6%93%8D%E4%BD%9C.html视频讲解https://…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
