【Unity】协程 Async

协程

协程是 Unity 内置的异步机制,通过 yield 暂停执行,实现任务在多帧中分段执行。与普通函数不同,协程可在执行过程中挂起和恢复,呈现"并发"效果,但本质上仍运行于主线程。若在协程中进行耗时操作,仍会导致主线程阻塞。因此,协程更适合处理异步事件的调度,而非需要多线程计算的任务。

  • StartCoroutine() 是启动器,不是执行体
  • yield return StartCoroutine() 是等待子协程完成的声明
  • Unity协程调度器在背后管理执行流程

优势

  • 使用简洁:在需要处理耗时的异步操作(如等待 HTTP 传输、资源加载、文件 I/O)时,官方建议优先考虑协程。
  • Unity 生命周期集成:协程由MonoBehaviour管理,随脚本或对象生命周期自动中止。比如当GameObject被停用或销毁时,其上运行的协程也会停止。
  • 无需线程切换:协程运行在 Unity 主线程,不必担心线程安全,因为代码始终在主线程执行。

劣势

  • 依赖 MonoBehaviour
  • 无法直接获取返回值:协程返回类型为IEnumerator,无法直接提供结果。通常需通过回调、全局状态或等待协程结束来获取数据,不如Task<T>直接。
  • 错误处理复杂:在协程内不能直接使用try/catch捕获包含yield的代码块中的异常,这使得异常处理更加困难。未处理的异常可能导致游戏逻辑问题被掩盖。
  • 性能与GC开销:尽管单个协程开销小,但大量协程会增加垃圾回收压力并可能影响帧率(如装箱迭代器、WaitForSeconds等对象),尤其是在每帧更新后统一调度时。每次 yield 都产生新对象。

使用场景

需要按照顺序执行、需要暂停、运行比单个帧花费时间更长的操作。

  • 将对象移动到某个位置。
  • 为对象提供要执行的任务列表。
  • 淡入淡出视觉或音频。
  • 等待资源加载:如Resources.LoadAsync/SceneManager.LoadSceneAsync
  • 网络请求封装:先 UnityWebRequest.SendWebRequest(),然后yield return request 等待请求完成,再检查结果。

yield return

Yield 表示该方法是一个迭代器 (IEnumerator),它将在多个帧上执行,而 return 与常规函数一样,在该点终止执行并将控制权传递回调用方法。

不同之处在于,对于协程,Unity 知道从上次中断的地方继续该方法。yield return 后面的内容将指定 Unity 在继续之前将等待多长时间。

  • yield return null - 等待下一帧
  • yield return new WaitForSeconds(秒数) - 等待一段时间

对于重复延迟,可以创建一个对象优化性能。

WaitForSeconds delay = new WaitForSeconds(1); // 创建对象Coroutine coroutine;void Start(){StartCoroutine("MyCoroutine");}IEnumerator MyCoroutine(){int i = 100;while (i > 0){// Do something 100 timesi--;yield return delay; // 使用对象}// All Done!}
  • yield return new WaitForSecondsRealtime(秒数) - 实时等待秒数
  • yield return new WaitUntil(条件)/WaitWhile(条件) - 等待委托
    • yield return new WaitUntil(() => condition) → 等待条件成立
    • yield return new WaitWhile(() => condition) → 等待条件不再成立
1. 用外部函数
yield return new WaitUntil(IsEmpty);
bool void IsEmpty()
{...//返回true或false
}2. 用lambda表达式
IEnumerator CheckFuel()
{yield return new WaitWhile(() => fuel > 0);...
}
  • yield return new WaitForEndOfFrame() - 等待帧结束
    会等到 Unity 渲染完每个 Camera 和 UI 元素,然后再实际显示帧。这方面的典型用途是截取屏幕截图。
  • yield return StartCoroutine()- 等待另一个协程
void Start(){// 启动协程StartCoroutine(MyCoroutine());}IEnumerator MyCoroutine(){// 启动等待第二个协程yield return StartCoroutine(MyOtherCoroutine());}IEnumerator MyOtherCoroutine(){...yield return new WaitForSeconds(1);}

结束协程

  • yield break - 在协程完成前结束协程
  • StopCoroutine - 在协程外部停止协程
bool stopCoroutine;
Coroutine runningCoroutine;void Start(){runningCoroutine = StartCoroutine(MyCoroutine());}void Update(){if (stopCoroutine == true){StopCoroutine(runningCoroutine);stopCoroutine = false;}}IEnumerator MyCoroutine(){// Coroutine stuff...}
  • StopAllCoroutines()- 停止MonoBehaviour上的所有协程
    需要从启动它们的行为中调用 。

其他

  • 推荐网址介绍

Async

async 关键字用于定义异步方法,配合 await 使用,可以在不阻塞Unity主线程的情况下执行耗时任务(如网络请求、文件I/O),从而使主线程保持流畅。

优势

  • 同步代码结构类似:有线性的代码执行流程,并且支持直接返回值。
  • 错误处理方便:可以用try-catch捕捉错误处理。
  • 高效的任务组合:内置并行处理机制
var task1 = LoadPlayerDataAsync();
var task2 = LoadLevelDataAsync();await Task.WhenAll(task1, task2); // 并行等待
  • 性能优化:状态机更轻量(特别是配合 UniTask);更少的 GC 压力。

劣势

  • Unity 集成问题:需要处理线程上下文
  • 时间控制复杂:默认不受 Time.timeScale 影响,需要手动实现游戏时间等待
  • 生命周期管理复杂:需要手动取消任务

使用场景

  • 网络请求和 I/O 操作
  • 复杂异步逻辑组合
  • 后台线程和 CPU 密集型任务
  • 需要精细错误处理的场景

关键字

  • Task:表示一个异步操作,用于执行异步任务并返回结果。
  • async 关键字:用于修饰方法,表明该方法是异步的,可以使用 await 进行异步调用。
  • await 关键字:用于等待异步操作完成,避免阻塞主线程。异步方法在碰到await表达式之前都是使用同步的方式执行。

对比

异步加载资源对比:

IEnumerator LoadAssetsCoroutine()
{// 顺序加载ResourceRequest request1 = Resources.LoadAsync<Texture>("Texture1");yield return request1;ResourceRequest request2 = Resources.LoadAsync<Texture>("Texture2");yield return request2;// 并行加载(有限支持)ResourceRequest[] requests = new ResourceRequest[3];for (int i = 0; i < 3; i++) {requests[i] = Resources.LoadAsync<GameObject>($"Prefab_{i}");}// 手动等待所有完成while (requests.Any(r => !r.isDone)) {yield return null;}Debug.Log("All assets loaded");
}
async Task LoadAssetsAsync()
{// 顺序加载var texture1 = await Resources.LoadAsync<Texture>("Texture1").AsTask();var texture2 = await Resources.LoadAsync<Texture>("Texture2").AsTask();// 并行加载var loadTasks = new List<Task>();for (int i = 0; i < 3; i++) {loadTasks.Add(Resources.LoadAsync<GameObject>($"Prefab_{i}").AsTask());}await Task.WhenAll(loadTasks);Debug.Log("All assets loaded");
}

代码结构与可读性对比:

async/await 允许按照同步代码的思维方式编写异步逻辑,可以直接返回值,像同步方法一样调用其他异步方法。

IEnumerator LoadGameData()
{// 1. 加载玩家数据UnityWebRequest playerReq = UnityWebRequest.Get(playerDataURL);yield return playerReq.SendWebRequest();PlayerData player = JsonUtility.FromJson<PlayerData>(playerReq.downloadHandler.text);// 2. 加载关卡数据UnityWebRequest levelReq = UnityWebRequest.Get(levelDataURL);yield return levelReq.SendWebRequest();LevelData level = JsonUtility.FromJson<LevelData>(levelReq.downloadHandler.text);// 3. 初始化游戏InitializeGame(player, level);
}
async Task LoadGameDataAsync()
{// 1. 加载玩家数据PlayerData player = await LoadPlayerDataAsync();// 2. 加载关卡数据LevelData level = await LoadLevelDataAsync();// 3. 初始化游戏InitializeGame(player, level);
}async Task<PlayerData> LoadPlayerDataAsync()
{UnityWebRequest req = UnityWebRequest.Get(playerDataURL);await req.SendWebRequest();return JsonUtility.FromJson<PlayerData>(req.downloadHandler.text);
}

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

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

相关文章

《揭秘!10 分钟洞悉 Prompt、Function Calling、MCP 与 AI agent 奥秘》

Prompt、Function Calling、MCP、AI agent这些术语频繁闯入我们的视野&#xff0c;它们到底都是什么、有啥关系。只需十分钟&#xff0c;咱们抽丝剥茧&#xff0c;揭开它们的神秘面纱&#xff0c;轻松掌握这些关键概念 并了解AI agent 完整执行流程。 一、提示词&#xff08;P…

决策树(回归树)全解析:原理、实践与应用

文章目录一、概述1.1 介绍1.2 回归树和分类树区别二、重要参数、属性及接口2.1 criterion&#xff08;不纯度衡量指标&#xff09;2.2 回归树如何工作&#xff08;核心流程拆解&#xff09;三、用回归树拟合正弦曲线&#xff08;实战案例&#xff09;3.1 绘制正弦曲线3.2 为正弦…

【盘古100Pro+开发板实验例程】FPGA学习 | HDMI 回环实验

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com) 1. 实验简介 实验目的&#xff1a; 完成 HDMI 回环实验 实验环境&#xff1a; Window11 PDS2022.2-SP6.4 硬件环境…

鸿蒙系统PC安装指南

鸿蒙系统PC安装指南一、安装DevEco Studio集成开发环境二、下载鸿蒙系统PC三、启动鸿蒙系统及使用一、安装DevEco Studio集成开发环境首先访问华为官网上&#xff0c;注册并登录华为账号&#xff0c;以开始下载所需的软件。若尚未注册&#xff0c;请先注册一个。在官网页面中&a…

三十九、【扩展工具篇】Allpairspy 组合用例生成器:智能设计高效测试集

三十九、【扩展工具篇】Allpairspy 组合用例生成器:智能设计高效测试集 前言 准备工作 第一部分:后端实现 - `allpairspy` API 1. 创建 `allpairspy` 服务 2. 创建 `allpairspy` API 视图 3. 注册 API 路由 第二部分:前端实现 - `Allpairspy` 工具界面 1. 创建 API 服务 (`s…

ZooKeeper 深度实践:从原理到 Spring Boot 全栈落地

在 Kubernetes 为主流注册发现的今天&#xff0c;给出如何在 Spring Boot 中基于 ZooKeeper 实现服务注册/发现、分布式锁、配置中心以及集群协调的完整代码与最佳实践。所有示例均可直接复制运行。 1. ZooKeeper 架构与核心原理 1.1 角色 Leader&#xff1a;处理写请求&…

可验证随机函数-VRF

可验证随机函数&#xff08;Verifiable Random Function, VRF&#xff09;是一种结合密码学技术的伪随机数生成器&#xff0c;其核心特点是生成的随机数可被公开验证&#xff0c;且具有不可预测性和唯一性。以下是VRF的详细解析&#xff1a;1. 基本定义与核心特性 可验证性&…

极客大挑战2020(部分wp)

Roamphp1-Welcome 405请求方法不允许&#xff0c;改一下请求方法 数组绕过&#xff0c;在页面搜索flag即可&#xff01;本题&#xff1a;就是知道了405是请求方法不允许&#xff01; Roamphp2-Myblog&#xff08;zip协议加文件包含&#xff09; 首先进来就是一个博客页面&…

ESP32 外设驱动开发指南 (ESP-IDF框架)——GPIO篇:基础配置、外部中断与PWM(LEDC模块)应用

目录 一、前言 二、GPIO 2.1 GPIO简介 2.2 GPIO函数解析 2.3 LED驱动 2.4 KEY驱动 三、EXIT 3.1 EXIT简介 3.2 EXIT函数解析 3.3 EXIT驱动 四、LEDC 4.1 PWM原理解析 4.2 ESP32的LED PWM控制器介绍 4.3 LEDC函数解析 4.3.1 SW_PWM 4.3.2 HW_PWM 4.4 LEDC驱动 …

鸿蒙 ArkWeb 加载优化方案详解(2025 最佳实践)

适用平台&#xff1a;HarmonyOS NEXT / API 10 关键词&#xff1a;ArkWeb、WebviewController、NodeController、预加载、预连接、预渲染、性能优化一、前言&#xff1a;为什么必须优化 ArkWeb 加载&#xff1f;在鸿蒙生态中&#xff0c;ArkWeb 是系统级的 Web 容器引擎&#x…

JavaScript案例(乘法答题游戏)

项目概述 使用原生JavaScript实现一个乘法答题游戏&#xff0c;随机生成乘法题目&#xff0c;判断答案正误并记录分数&#xff0c;通过localStorage实现分数持久化存储。 核心功能需求 随机题目生成&#xff1a;动态生成1-10之间的乘法题答题交互&#xff1a;输入答案并提交…

EXCEL删除数据透视表

wps版 点击红框内任意区域 在顶部工具栏选择删除Excel 版 1.点击红框内任意区域2. 点击Enable Selection,再按住键盘上的Delete键&#xff0c;记住不是Backspace键

Python 飞机大战:从零开发经典 2D 射击游戏

引言&#xff1a;重温经典游戏开发 飞机大战作为经典的 2D 射击游戏&#xff0c;承载了许多人的童年回忆。使用 Python 和 Pygame 开发这样一款游戏不仅能重温经典&#xff0c;更是学习游戏开发绝佳的实践项目。本文将带你从零开始&#xff0c;一步步实现一个完整的飞机大战游…

Vue项目中实现浏览器串口通信:Web Serial API完整指南

前言 在现代Web开发中&#xff0c;随着IoT设备和硬件交互需求的增长&#xff0c;浏览器与串口设备的通信变得越来越重要。本文将详细介绍如何在Vue项目中使用Web Serial API实现串口通信功能&#xff0c;为开发者提供一个完整的解决方案。 技术背景 传统方案的局限性 传统的串口…

Github怎么只下载某个目录文件?(Git稀疏检出、GitZip for Github插件、在线工具DownGit)Github下载目录

文章目录**方法一&#xff1a;使用 Git 的稀疏检出&#xff08;Sparse Checkout&#xff09;**&#xff08;略&#xff09;**步骤&#xff1a;****方法二&#xff1a;使用 SVN 下载特定目录**&#xff08;略&#xff09;**步骤&#xff1a;****方法三&#xff1a;使用浏览器插件…

把“多视图融合、深度传感”组合在一起,今天分享3篇3D传感技术干货

关注gongzhonghao【计算机sci论文精选】3D传感技术起源于工业领域高精度测量需求&#xff0c;早期以激光三角测量、结构光等技术为主&#xff0c;主要服务于制造业的零部件检测与形变分析。随着消费电子智能化升级&#xff0c;苹果iPhone X的Face ID将结构光技术推向大众市场&a…

dubbo源码之消费端启动的高性能优化方案

一、序言 dubbo作为一款最流行的服务治理框架之一,在底层做了很多的优化,比如消费端在启动的时候做了很多性能提升的设计,接下来从连接的层面、序列化功能的层面进行介绍下。 二、优化点 1、消费端在服务启动的时候会调用DubboProtocol类的protocolBindingRefer方法来创建…

zookeeper常见命令和常见应用

前言 ZooKeeper自带一个交互式命令行工具&#xff08;通过zkCli.sh或zkCli.cmd启动&#xff09;&#xff0c;提供了一系列操作ZooKeeper数据节点的命令 下面我们对zookeeper常用命令进行介绍 使用prettyZoo命令行窗口 使用prettyZoo客户端链接zookeeper 打开zookeeper命令…

前端异步任务处理总结

一、异步任务常见场景网络请求&#xff1a;fetch()、axios 等 API 调用定时操作&#xff1a;setTimeout、setInterval用户交互&#xff1a;事件监听回调资源加载&#xff1a;图片/脚本动态加载Web Workers&#xff1a;后台线程计算二、核心处理方案1. Promise&#xff08;ES6&a…

机器学习第三课之逻辑回归(二)LogisticRegression

目录 简介 一.分类评估⽅法 1.混淆矩阵 2.精确率(Precision)与召回率(Recall) 3.F1-score 4.分类评估报告api 2.正则化惩罚 3.⽋拟合和过拟合 4.K折交叉验证 5.代码分析 简介 接上一篇博客最后 机器学习第二课之逻辑回归&#xff08;一&#xff09;LogisticRegres…