Unity中的异步编程【1】—— Unity与async 、 await

2023-11-17

新手在Unity里写东西,一个方法的内容如果写复杂了,容易把Uinty写死,就会卡帧,用流行的话来总结就是:在Update里面活生生把天聊死了。

此外,如果新手才入门,不擅长使用消息、事件来进行异步的统筹,一门心思在Update里面实现各种有延时有顺序的步骤,于是自己把自己绕晕不说,程序又难调试,难修改,更甚——帧率低下…

那么用协程来实现异步…聪明…

但,还有比协程更好用的异步框架,那就是UniTask


一、什么是异步:async和await是啥

异步这个概念一言难尽,里面涉及到很多上古时候的知识:单核/多核,单线程/多线程,并发/并行,阻塞/非阻塞…

举一个例子:
小赵夫妻响应祖国的号召,夫妻二人7年之内哗啦啦生了3个娃娃。对这对夫妻来说,他们生娃只能一胎一胎的生,所以小赵家生三娃这件事情就是单线程,而且是阻塞式的。
又过了几年,人们纷纷进城,村里的人越来越少,于是大家响应号召要多多生娃,特别是赵庄的赵太爷在县太爷面前拍了胸脯:2年之内,我们赵庄要增加100个新生儿。
于是赵太爷在村里做了动员,大伙儿也积极响应,纷纷备孕。于是赵庄生100个娃这件事情变成了多线程,而且是非阻塞的(大家一起生——这叫多线程,张家怀孕不会影响李家怀孕——这叫非阻塞)。

二、C#(.Net)中的异步

.Net自C#5开始,大概2012年前后,开始引入了异步编程(async和await),有了异步之后,很少需要手动去开线程了,而且业务更好理解,代码更加清晰。

同步举例:解放前的辛家庄有十户人,他们共用一个灶做饭,于是只能轮着顺序做饭…

在这里插入图片描述
以上做饭的总耗时为10

代码清单

using System;
using System.Threading.Tasks; //关键的包

public static void Cooking(int i ){
    Console.WriteLine($"第{i}户家庭开始做饭...");     
    Task.Delay(1000).Wait();
    Console.WriteLine($"第{i}户家庭做饭结束");    
}

public static void TestCooking(){
    for(int i = 0;i<10;i++)
    {
        Cooking(i);
    }
}

TestCooking();

异步举例:现在他们富裕了,每家都有一个灶,于是做饭的时候全村炊烟袅袅,大家各做各的,这做饭就成了并发(并行)。

张家做饭和李家做饭和不干涉,互不阻碍。

以下是他们十家一起做饭的壮观情景:
请注意红框中的【async】和【await】关键字
在这里插入图片描述
各家在各家做饭,虽然同一时间开始做,但总耗时为1

代码清单

public static async Task Cooking(int i ){
    Console.WriteLine($"第{i}户家庭开始做饭...");     
    await Task.Delay(1000);
    Console.WriteLine($"第{i}户家庭做饭结束");    
}

public static async Task TestCooking(){
    var allTasks = new List<Task>();
    for(int i = 0;i<10;i++)
    {
        allTasks.Add(Cooking(i));
    }
    
    await Task.WhenAll(allTasks.ToArray());
}

await TestCooking();

三、 Unity中的异步

  • 问题的提出:点了按钮,隔三秒启动发动机,发动机转4秒,然后停机。以上内容把它写在一个方法里面。
    解决办法1:一般大家能够想到的就是协程,没问题,这是Unity标准玩法,但是协程没有返回值,也不能好好调试…

解决办法2:聪明的你肯定想到.NET的 async和await了,但是,不好意思,Unity不能完美支持,比如在WebGL里面,就不支持多线程,async和await背后是多线程。所以,此路不通。

解决办法3:UniRX和UniTask
UniRX是上世代的产物,响应式编程兴起的时候创建的项目,至今已经进入稳态,官网特别说明,如果你要搞异步编程,那么就用UniTask,因为异步功能已经从UniRX拆分到UniTask了。

用UniTask完成以上业务:
点击【Button】后,启动发动机…停止发动机:
在这里插入图片描述
代码清单:

using UnityEngine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks;//关键包
public class mytest : MonoBehaviour
{
    public Button myBtn;

    // Start is called before the first frame update
    void Start()
    {

        myBtn.onClick.AddListener(async ()=> 
        {
            //隔三秒启动发动机,发动机转4秒,然后停机
            Debug.Log($"{Time.realtimeSinceStartup}: 预热三秒");
            await UniTask.Delay(System.TimeSpan.FromSeconds(3),ignoreTimeScale:false);
            Debug.Log($"{Time.realtimeSinceStartup}: 启动发动机,发动机开始运转");
            await UniTask.Delay(System.TimeSpan.FromSeconds(4), ignoreTimeScale: false);
            Debug.Log($"{Time.realtimeSinceStartup}: 发动机停机");
        });
    }
}

四、发布和测试:WebGL发布并测试ok

在这里插入图片描述

五、附录

1、C#异步编程
2、UniRX —— Unity响应式编程
3、UniTask—— Unity异步编程

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity中的异步编程【1】—— Unity与async 、 await 的相关文章

  • 如何使用不同的基本路径托管 Blazor WebAssembly 应用程序

    我有一个 Blazor Webassemble NET 托管应用程序 在我们托管它的服务器上 应用程序的基本路径将是mydomain com coolapp 因此 为了尝试让应用程序在服务器上正确呈现 我一直遵循本页 应用程序基本路径 部分
  • 如何从经过身份验证的 SecurityToken 中获取声明

    我将令牌作为字符串传递到 SOAP 服务中 并验证了该令牌是否有效 我现在有一个 SecurityToken 在调试模式下我可以看到所有声明 特别是我想传递到另一个方法的 userId 声明 我似乎不知道如何获得这些索赔 现在 我解码了令牌
  • C++中类成员函数相互调用有什么好处?

    我是 C 新手 我发现下面的编程风格对我来说很有趣 我在这里写了一个简化版本 include
  • 获取列表框中视图中的项目

    我有一个 ListBox 其属性 VirtualizingStackPanel VirtualizationMode 设置为 回收 我正在绑定一个自定义集合 实现IList and IList
  • 如何在 Linux 上重新实现(或包装)系统调用函数?

    假设我想完全接管 open 系统调用 也许要包装实际的系统调用并执行一些日志记录 一种方法是使用 LD PRELOAD http scaryreasoner wordpress com 2007 11 17 using ld preload
  • 在 C# 中解析 JS Date.toIsoString

    我需要将 JS 日期存储为 ISO 8601 日期 我目前正在从格式为 2019 06 22T00 00 00 000Z 的表单中获取日期 正如 JS 的 toIsoString 方法所期望的那样 当这个日期传递到我的 API 控制器时 我
  • 公交车公共交通算法

    我正在开发一个可以查找公交路线的离线 C 应用程序 我可以提取时间表 巴士 路线数据 我正在寻找适用于基本数据的最简单的解决方案 可以使用什么算法来查找从巴士站 A 到巴士站 B 的路线 是否有适用于 C Java 的开源解决方案 数据库的
  • 重载算术运算符

    赋值运算符可以声明为 T 运算符 const t 在类中 但不能以这种方式定义算术运算符 它必须是友元函数 我不明白为什么 你能解释一下吗 算术运算符不必须是友元 那么你可以这样定义 MyClass MyClass operator con
  • 从图像创建半透明光标

    是否可以从图像创建光标并使其半透明 我目前正在拍摄自定义图像并覆盖鼠标光标图像 如果我可以将其设为半透明 那就太好了 但不是必需的 销售人员喜欢闪亮的 目前正在做这样的事情 Image cursorImage customImage Get
  • 注入包含接口的所有已注册实现的 Enumerable

    给出以下接口 public interface IMyProcessor void Process 我希望能够注册多个实现 并让我的 DI 容器将它们的可枚举注入到这样的类中 public class MyProcessorLibrary
  • 更改私有模块片段是否会导致模块重新编译?

    On 此页面有关 C 20 模块功能 https www modernescpp com index php c 20 modules private module fragment and header units 我发现了这样的说法 借
  • C# 可以为控制台应用程序部分类“程序”类吗?

    我想知道是否可以将为任何控制台应用程序创建的默认 程序 类更改为部分类 我想这样做是因为我想要更好的组织 而不是将所有方法都放在按区域分类的 1 个文件中 对我来说 将某些方法类别放在单独的文件中会更有意义 我对分部类的理解是 它是多个文件
  • 如何在VS2005中使用从.bat而不是.exe启动的外部程序进行调试?

    在我的 c 项目的调试属性中 我选择了 启动外部程序 并选择了我希望将调试器附加到的程序的 exe 但是 现在我需要从 bat 文件而不是 exe 启动程序 但 VS2005 似乎不允许这样做 这可能吗 编辑 为了澄清 我需要调试从 bat
  • 在一个解决方案中调用不同项目的方法

    1 个解决方案中有 3 个项目 我对第一个项目中的主文件进行的主要操作 但是我需要调用第三个项目中的方法并使用类 例如 第三个项目有 public DataClasses1DataContext base global WindowsFor
  • c++ - <未解析的重载函数类型>

    在我的班级里叫Mat 我想要一个将另一个函数作为参数的函数 现在我有下面 4 个函数 但是在调用 print 时出现错误 第二行给了我一个错误 但我不明白为什么 因为第一行有效 唯一的区别是功能f不是班级成员Mat but f2是 失败的是
  • C# 多维数组解析

    我有一个多维数组 内容在调试器中看起来像这样 数组设置为 String s new String 6 4 A B Yes C A B Yes C A B No C A B Yes C A B Yes C A B Yes C A B No C
  • 跟踪白色背景中的白球(Python/OpenCV)

    我在 Python 3 中使用 OpenCV 来检测白场上的白 黑球 并给出它的精确 x y 半径 和颜色 我使用函数 cv2 Canny 和 cv2 findContours 来找到它 但问题是 cv2 Canny 并不总是检测到圆的完整
  • C++ 中的析构函数

    我的 AB h 文件中有一个构造函数 class AB private int i public AB i 0 constructor AB i 0 destructor virtual void methodA unsigned int
  • java有类似C#的属性吗? [复制]

    这个问题在这里已经有答案了 C 属性 我的意思是 get 和 set 方法 是一个非常有用的功能 java 也有类似 C 的属性吗 我的意思是我们如何在 java 中实现类似以下 C 代码的内容 public string Name get
  • 如何使用 Microsoft Graph API 更新 MailboxSettings

    我想从不同的日历更新邮箱设置 如何构建可以通过 Microsoft Graph 更新 MailboxSetting 的请求 这是我的代码示例 但有例外 代码示例 User obj GraphServiceClient Users roomC

随机推荐

  • 【微调视觉-语言模型】Learning to Prompt for Vision-Language Models

    微调视觉 语言模型 Learning to Prompt for Vision Language Models 代码地址 论文简介 动机和思路 具体实现 Vision Language Pre training Context Optimi
  • vue 分页器组件+css动画效果

    全网都找了一遍没有找到符合UI需求的分页动画 于是就主动上手了 需求 1 分页最多显示9页 总页数最多显示无上限 2 点击下一页的时候需要有动画效果过度 如果当前页数是当前显示最后的一页 则停了当前显示最后的位置 但是点击下一页的时候需要用
  • C++ 和 Qt 6 跨平台开发

    特点 使用 Qt 6 和现代 C 进行跨平台开发 涵盖使用标准 C 17 和 Qt 6 功能跨多个平台编写 GUI 应用程序的基本要素 从 Qt 框架的基础开始 包括 Qt Creator 提供的功能 展示如何使用 Qt Widgets 创
  • C++ 类详解(Plus)

    过程性编程和面向对象编程的区别 之前在那篇博客上看到这个比喻 觉得特别恰当 挺容易让人理解的 现在分享一下 用面向过程的方法写出来的程序是一份蛋炒饭 而用面向对象写出来的程序是一份盖浇饭 所谓盖浇饭 北京叫盖饭 东北叫烩饭 广东叫碟头饭 就
  • opencv 中Mat的一些操作

    https my oschina net drjones blog 312876 http blog sina com cn s blog 66e177dd0102w9dv html 1 创建矩阵 OpenCV Java中矩阵就是一个类 M
  • sql server 分组,取每组的前几行数据

    sql中group by后 获取每组中的前N行数据 目前我知道的有2种方法 比如有个成绩表 里面有字段学生ID 科目 成绩 我现在想取每个科目的头三名 1 子查询 select from score s where StudentName
  • 深入理解设计原则之组件构建原则【软件架构设计】

    系列文章目录 C 高性能优化编程系列 深入理解软件架构设计系列 深入理解设计模式系列 高级C 并发线程编程 困难只能吓倒懦夫懒汉 而胜利永远属于攀登高峰的人 Difficulties can only be intimidated by a
  • java内存分页工具类

    hutool 依赖
  • Android 首次开机进入 Launcher3 前黑屏几秒的情况问题的总结

    Android 首次开机进入 Launcher3 前黑屏几秒的情况问题的总结 首先 让我们来探讨一下 Android 系统在首次开机时为何会出现黑屏几秒的情况 在 Android 系统启动过程中 首先会加载 Linux 内核 然后启动 An
  • 关于生成图片

    数组生成图片 image Image fromarray np uint8 arr arr的shape必须是3在后面 比如 375 500 3 tensor生成图片 trans transforms ToPILImage image tra
  • 华为OD机试 - 代表团坐车(Java)

    题目描述 某组织举行会议 来了多个代表团同时到达 接待处只有一辆汽车 可以同时接待多个代表团 为了提高车辆利用率 请帮接待员计算可以坐满车的接待方案 输出方案数量 约束 一个团只能上一辆车 并且代表团人数 代表团数量小于30 每个代表团人数
  • c++栈的练习题

    1 Problem Detail 入门 火车编组 追梦算法网 栈的练习题 include
  • System.UnauthorizedAccessException: Access to the path is denied

    这个异常一般是操作文件读写时发生 一般有以下四个原因 调用方没有所需的权限 该文件是一个正在使用的可执行文件 路径是一个目录 该文件只读
  • javascript中的数字校验

    javascript限制输入的只能是数字 判断event keyCode的值 并将它限定只能为数字 如果不是数字 则返回错误 如果是数字 则继续 我先介绍验证javascript是否是数字另一种方式 通过下面的函数来实现 function
  • Unity3D之MonoBehaviour

    Unity3D中的MonoBehaviour是一种基于组件的编程架构 用于开发游戏和应用程序 它是Unity引擎中用于创建行为的基类之一 并且可以让你通过重写其方法来定义对象在游戏运行时的行为 首先 在Unity中创建一个游戏对象并向其添加
  • 使用vue+echarts世界地图航线路线

    这是一个vue结合echarts做的船舶轨迹运行线路图 一 安装echarts npm install echarts 二 全局引入 在全局引入 需要在main js文件中 引入echarts import echarts from ech
  • Unity3D模型

    SolidWorks建模导入Unity 前言 使用的版本 SolidWorks导入3DMax 3DMax导入Unity 结尾 前言 本篇主要作为个人经验记录 因项目需要将SW的模型导入Unity中使用 但SW中建模为实体而Unity多为面
  • Java中创建对象时内存中的情况

    public class Phone public String brand public double price public String color public void call String name System out p
  • conda 国内源配置

    修改 condarc show channel urls true channels https mirrors tuna tsinghua edu cn anaconda cloud conda forge https mirrors t
  • Unity中的异步编程【1】—— Unity与async 、 await

    新手在Unity里写东西 一个方法的内容如果写复杂了 容易把Uinty写死 就会卡帧 用流行的话来总结就是 在Update里面活生生把天聊死了 此外 如果新手才入门 不擅长使用消息 事件来进行异步的统筹 一门心思在Update里面实现各种有