Unity中的异步编程——在Unity中使用 C#原生的异步(Task,await,async) - System.Threading.Tasks
Posted dzj2021
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity中的异步编程——在Unity中使用 C#原生的异步(Task,await,async) - System.Threading.Tasks相关的知识,希望对你有一定的参考价值。
一、UniTask(Cysharp.Threading.Tasks)和Task(System.Threading.Tasks)的区别
- 1、System.Threading.Tasks中的Task是.Net原生的异步和多线程包。
- 2、UniTask(Cysharp.Threading.Tasks)是仿照.Net原生的Task,await,async开发的一个包,该包专门服务于Unity,所以取名UnityTask,简称UniTask。
- 3、既然有Task了,为啥还要搞一个UniTask
- (1)Task可以用在PC和android上,但是在WebGL上则会报错(与多线程的支持有关),你可以退而求其次,使用协程实现异步等待。但是这样容易形成两套代码,增加工作量。
- (2)UniTask则是用一套代码打天下【一套写法,适用于PC,Android,WebGL等等】,UniTask用协程把await,async统一到多个运行平台。
背景:之前用Unity2020 + UniTask开发的项目,结果用户的需求是要集成到Unity2017.4.37的一个工程文件里面,所有只能返祖了。
二、为Task增加新的功能
- 1、UniTask有WaitUntil(),而Task没有,只能手动添加一个
/// <summary>
/// 方法:WaitUntil
/// </summary>
/// <param name="predicate">条件语句</param>
/// <param name="sleep">delay事件</param>
/// <returns>Task</returns>
public static async Task WaitUntil(Func<bool> predicate, int sleep = 50)
while (!predicate())
await Task.Delay(sleep);
- 2、UniTask有DelayFrame(),而Task没有,手动添加一个
/// <summary>
/// 方法:等待X帧
/// </summary>
/// <returns>Task</returns>
public static async Task DelayFrame(int count)
var current = Time.frameCount;
while (Time.frameCount - current > count)
await Task.Yield();
- 3、UniTask中为多种UI实现了异步点击的方法,在Task模式下,如何为一个Button打造一个异步点击方法——OnClickAsync
- (1)使用扩展方法来实现
- (2)给一个button的OnClick绑定一个方法,发生点击事件时,更改一个bool标记
- (3)用Task的await来循环等待用于标记Button点击的bool标记是否为true
- (4)取消button上OnClick中之前绑定的方法
- (5)返回
/// <summary>
/// 为Button定制一个扩展方法:点击事件的异步等待
/// </summary>
/// <param name="button">按钮Button</param>
/// <param name="delayMs">循环等待中delay的时间-毫秒</param>
/// <returns>Task</returns>
public static async Task OnClickAsync(this Button button,int delayMs = 50)
bool clicked = false;
UnityAction ClickAction = () =>
clicked = true;
//Debug.Log($"ClickAction() was called Time.realtimeSinceStartup");
;
//Debug.Log("添加侦听");
button.onClick.AddListener(ClickAction); //此处不能用兰姆达,不然传入的是临时定义的方法,而不是提前定义的。
while (!clicked)
await Task.Delay(delayMs); //等待时间【ms毫秒】
//Debug.Log("移除侦听");
button.onClick.RemoveListener(ClickAction);
ClickAction = null;
三、代码清单
代码【1】——扩展Task
using System;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
/// <summary>
/// Task扩展工具 【System.Threading.Tasks 】
/// not UniTask 【Cysharp.Threading.Tasks】
/// </summary>
public static class TaskUtils
/// <summary>
/// 方法:WaitUntil
/// </summary>
/// <param name="predicate">条件语句</param>
/// <param name="sleep">delay事件</param>
/// <returns>Task</returns>
public static async Task WaitUntil(Func<bool> predicate, int sleep = 50)
while (!predicate())
await Task.Delay(sleep);
/// <summary>
/// 方法:等待X帧
/// </summary>
/// <returns>Task</returns>
public static async Task WaitFrame(int count)
var current = Time.frameCount;
while (Time.frameCount - current > count)
await Task.Yield();
/// <summary>
/// 方法:等待X帧
/// </summary>
/// <returns>Task</returns>
public static async Task DelayFrame(int count)
var current = Time.frameCount;
while (Time.frameCount - current > count)
await Task.Yield();
【2】——测试Task
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Threading.Tasks;
using System;
/// <summary>
/// 按钮被点击的事件绑定
/// </summary>
public class ButtonClicked : MonoBehaviour
public Button myButton;
// Use this for initialization
void Start ()
Func<Task> Flow = async() =>
while (true)
Debug.Log($"等待按钮被点击-Time.realtimeSinceStartup");
await myButton.OnClickAsync();
Debug.Log($"按钮点击完成-Time.realtimeSinceStartup");
;
Flow();
- 【3】测试结果
测试环境Unity2017.4.37 Editor + Win10
我不能将脚本分配给 UNITY 中的按钮?
【中文标题】我不能将脚本分配给 UNITY 中的按钮?【英文标题】:I can't assign scripts to buttons in UNITY? 【发布时间】:2019-05-11 04:22:56 【问题描述】:我刚开始探索 Unity,我正在使用 UNITY 2D 制作游戏。 我决定从一个简单的菜单屏幕开始习惯 UNITY。 我制作了菜单并继续对按钮进行编程。
但是,当我将脚本(或持有脚本的游戏对象)拖入单击部分的按钮并尝试选择我的功能时,它不会显示。
我的统一窗口
点击脚本按钮中的经理。
我的 C# 代码(这是我第一次使用 C#)
我想知道的是:我做错了什么吗?统一的工作方式与我的理解不同吗?团结在做一些奇怪的事情吗?我该如何解决。
(对于奇怪的帖子布局我不知道为什么这样做)。
【问题讨论】:
Alex - 在第 9 分钟左右结帐this tutorial。 投票关闭是一个印刷错误,因为缺少;
已阻止 Unity 编译新脚本,以便可以在检查器中访问它。
【参考方案1】:
你需要:
-
在 Buttons 类的行尾添加分号
将 Buttons 类添加到场景中的 _Manager 游戏对象
【讨论】:
如果脚本在_Manager
GameObject上,应该没有问题。【参考方案2】:
只需在代码末尾插入;
就可以了。您应该注意到编译器抱怨缺少分号。另外,请确保将您的脚本附加到_Manager
GameObject。
【讨论】:
以上是关于Unity中的异步编程——在Unity中使用 C#原生的异步(Task,await,async) - System.Threading.Tasks的主要内容,如果未能解决你的问题,请参考以下文章
Unity 在使用 Firebase 数据库进行异步编程时崩溃