Unity协程学习心得

前言

个人总结的一些Unity协程学习心得,如有不对请在评论区指出一起学习!感谢。

在Unity编程中谈到异步逻辑,可以考虑使用协程来实现。协程(Coroutine)在Unity中的主要作用就是把一个任务暂停(挂起),并在下一帧(或之后的某一时间点)继续。常见案例有网络请求、临时计时器、资源加载、打字机特效等。需要注意的是,协程不是线程,协程是在主线程中执行的。使用协程可以不用考虑同步和锁的问题。

1、C#迭代器

官方文档:遍历集合 - C# | Microsoft Learn

在了解并使用协程之前,我们可以先扩展一下关于C#迭代器的知识,方便我们理解什么是yield

迭代器方法或 get 访问器可对集合执行自定义迭代。 迭代器方法使用 yield return 语句返回元素,每次返回一个。 到达 yield return 语句时,会记住当前在代码中的位置。 下次调用迭代器函数时,将从该位置重新开始执行。迭代器方法或 get 访问器的返回类型可以是 IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>。

在C#中,yield可以粗浅的理解为“产出”。用于实现迭代器,逐步产出序列中的元素

案例:写一个返回数字的迭代器方法

void Start()
{var numbers = GetNumbers();while (numbers.MoveNext()){Debug.Log($"t_Coroutine {numbers.Current}");}
}IEnumerator GetNumbers()
{yield return 0;yield return 1;yield return 200;
}

 输出:

但是在Unity中,我们只用到了IEnumerator来创建协程方法。因此,我着重介绍一下IEnumerator接口。

1.1 IEnumerator

public interface IEnumerator
{object Current{get;}bool MoveNext();void Reset();
}

可以看到其实迭代器内部很简单。

Current是当前迭代器指向的对象;MoveNext()是移动指针指向下一个对象,如果是最后一个对象则返回false;Reset()是重置为最初状态。

2、协程基本语法

2.1 写一个简单的协程

协程开始时,会顺序执行yield return null;之前的代码,遇到yield return 会被挂起(暂停),等待指定时间后,从被挂起的地方继续往下执行。

using System.Collections;
using UnityEngine;public class CoroutineExample : MonoBehaviour
{void Start(){StartCoroutine(MyCoroutine());}IEnumerator MyCoroutine(){// 开启协程就会执行的逻辑Debug.Log("t_Coroutine Start Coroutine");yield return null;  //在这里被暂停,暂停1帧//挂起并恢复之后的逻辑Debug.Log("t_Coroutine Wait One Frame After");yield return new WaitForSeconds(2); //在这里被暂停,暂停2秒Debug.Log("t_Coroutine Wait Two Seconds After");//协程结束}
}

输出:

 

2.2 yield return的不同用法

2.2.1 yield return null 与 yield return 1

在Unity协程中,yield return null; 和 yield return 1; 实际上是等效的,二者都会暂停协程的执行并在下一帧继续执行。即等待一帧

之所以等效,是因为yield return会返回一个值给Unity的协程调度器,这个值用于决定协程何时继续。null和任意整数(例如1)都会导致协程在下一帧恢复执行。

2.2.2 yield break

立即停止协程

案例:可以看到Break After并没有被打印出来,在此之前协程就停止了

using System.Collections;
using UnityEngine;public class CoroutineExample : MonoBehaviour
{void Start(){StartCoroutine(MyCoroutineBreak());}IEnumerator MyCoroutineBreak(){Debug.Log("t_Coroutine Start MyCoroutineBreak");yield return null;  //在这里被暂停,暂停1帧Debug.Log("t_Coroutine Wait Two Seconds After");yield break;//协程结束Debug.Log("t_Coroutine Break After");}
}

输出: 

2.2.3 yield return StartCoroutine(OtherCoroutine())

协程是可以嵌套的,可以使用yield return StartCoroutine(OtherCoroutine()),等待OtherCoroutine协程方法执行完毕后,再继续往下执行

案例:

void Start()
{Debug.Log("t_Coroutine Start1");StartCoroutine(TestCoroutine());Debug.Log("t_Coroutine Start2");
}IEnumerator TestCoroutine()
{Debug.Log("t_Coroutine test1");yield return StartCoroutine(LoadCoroutine());Debug.Log("t_Coroutine test2");
}IEnumerator LoadCoroutine()
{Debug.Log("t_Coroutine load 1");yield return null;Debug.Log("t_Coroutine load 2");
}

输出:

 

 2.2.4 其他用法

yield return new WaitForEndOfFrame();//等待帧结束yield return new WaitForSeconds(1f);//等待1秒;yield return WebRequest();//等待到网络请求结束返回结果的时候;yield return new WaitUntil()//等待到结果返回为true的时候yield return new WaitWhile()//等待到结果返回为false的时候

2.3 开启 / 停止协程

2.3.1 直接开启一个协程

无法控制暂停,直接调用协程方法开启

StartCoroutine(MyCoroutine());

2.3.2 用变量控制协程

private Coroutine myCoroutine;
myCoroutine = StartCoroutine(MyCoroutine());//开启协程
StopCoroutine(myCoroutine);//停止协程

2.3.3 用协程方法名控制协程

StartCoroutine("MyCoroutine");//开启协程
StopCoroutine("MyCoroutine");//停止协程

2.3.4 停止所有正在运行的协程

会停止该对象上所有正在运行的协程,慎用!

当一个游戏对象(GameObject)把Active设置为false,即SetActive(false),也会停止该对象上附加的协程。

调用Destroy(GameObject)时,Unity会调用OnDisable(),处理并停止协程。在这一帧结束时,会调用OnDestroy()。

StopAllCoroutines();

3、学习参考博客

官方文档:Unity - Manual: Coroutines

通俗易懂博客(建议先看这个,很好理解):Unity C#中协程/携程Coroutine简单易懂详解-CSDN博客

更进一步理解:Unity StartCoroutine - 简书

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

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

相关文章

智慧园区建设方案(Word)

1. 楼栋管理 2. 物业管理 3. 安防管理 4. 门禁管理 5. 停车管理 6. 能源管理 7. 环保管理 8. 园区生活服务 9. 招商管理 10. 收费中心 11. 园区地图 12. 门户网站 软件整套原件获取&#xff1a;本文末个人名片。

使用DPO微调大模型Qwen2详解

简介 基于人类反馈的强化学习 (Reinforcement Learning from Human Feedback&#xff0c;RLHF) 事实上已成为 GPT-4 或 Claude 等 LLM 训练的最后一步&#xff0c;它可以确保语言模型的输出符合人类在闲聊或安全性等方面的期望。但传统的RLHF比较复杂&#xff0c;且还需要奖励…

BabylonJS 6.0文档 Deep Dive 动画(四):通过动画排序制作卡通片

一种最为直接的方法是为每个动画剪辑&#xff08;Animatin Clip&#xff09;指定开始时间&#xff0c;最终形成一个卡通动画&#xff08;Cartoon&#xff09;。 1. 设计 1.1 概述 动画的脚本如下&#xff1a; 摄像机显示了一栋带门的建筑物。摄像机靠近门并停止。门打开&am…

掌控数据流:深入解析 Java Stream 编程

Java 8 引入了一种新的抽象称为流&#xff08;Stream&#xff09;&#xff0c;它可以让你以一种声明的方式处理数据。Java 8 Stream API 可以极大提高 Java 程序员的生产力&#xff0c;使代码更简洁&#xff0c;更易读&#xff0c;并利用多核架构进行外部迭代。这里将详细介绍 …

【NoSQL数据库】Redis简介

Redis Redis简介 Redis关系型数据库和非关系型数据库Redis 简介redis速度快的原因 Redis 配置Linux 源码安装redis命令工具 关系型数据库和非关系型数据库 关系型数据库&#xff08;Relational Database&#xff09;和非关系型数据库&#xff08;Non-Relational Database&…

重学Spring总结

1、Spring框架的诞生 文章目录 1、Spring框架的诞生1、BeanFactory 快速入门1.1、BeanFactory完成了loC思想的实现&#xff1a;1)导入Spring相关的依赖&#xff1a;2)定义Uservice接口及其UserviceImpl实现类&#xff1b;3)创建Bean的配置资源文件&#xff0c;文件名最好为&…

新材料正不断推动模具3D打印行业发展

随着工业4.0的浪潮席卷全球&#xff0c;模具制造行业也迎来了技术革新的新纪元。3D打印技术以其独特的制造优势&#xff0c;正逐渐在模具制造领域崭露头角。然而&#xff0c;要实现模具3D打印技术的广泛应用&#xff0c;高性能的打印材料是不可或缺的关键因素。 材料是模具3D打…

【Golang】Map 稳定有序遍历的实现与探索:保序遍历之道

【Golang】Map 稳定有序遍历的实现与探索&#xff1a;保序遍历之道 大家好 我是寸铁&#x1f44a; 总结了一篇【Golang】Map 稳定有序遍历的实现与探索&#xff1a;保序遍历之道✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言&#x1f34e; 在计算机科学中&#xff0c;数据结…

【内存管理】内存管理概述

文章目录 内存管理硬件结构早期内存的使用方法分段分页逻辑地址&#xff0c;线性地址&#xff08;intel架构&#xff09;虚拟地址物理地址结构图 虚拟地址到物理地址的转换内存管理总览系统调用vm_area_struct缺页中断伙伴系统slab分配器页面回收反向映射KSMhuge page页迁移内存…

[AI Google] 使用 Gemini 取得更多成就:试用 1.5 Pro 和更多智能功能

总结 Google 正在为超过 35 种语言的 Gemini Advanced 订阅者推出 Gemini 1.5 Pro。此次更新包括 100 万个 token 的上下文窗口、改进的数据分析功能和增强的多模态图像理解。新功能包括用于自然对话的 Gemini Live、先进的规划工具和可定制的 Gems。更新还集成了更多 Google …

【MySQL】(基础篇五) —— 排序检索数据

排序检索数据 本章将讲授如何使用SELECT语句的ORDER BY子句&#xff0c;根据需要排序检索出的数据。 排序数据 还是使用上一节中的例子,查询employees表中的last_name字段 SELECT last_name FROM employees;输出结果&#xff1a; 发现其输出并没有特定的顺序。其实&#xf…

电子电气架构 --- 信息安全测试模糊测试

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

Objective-C的初始化方法中,应该如何读写属性

除非有明确的原因需要使用setter, getter, 否则总是应该直接访问, 也就是直接使用实例变量&#xff08;也称为 iVar&#xff09;来读写数据 理由&#xff1a; 避免子类覆盖setter方法的影响&#xff1a;若在初始化方法中使用setter方法, 使用此方法实例化子类, 可能会调用子类…

纯理论容器实现的原理

近期在复习容器的原理&#xff0c;希望这篇文章可以帮助到大家。 一、什么是容器&#xff1f; 容器本质上就是主机上的一个进程。这个进程拥有自己的用户空间并且和主机共享内核空间。 容器内的进程可以通过系统调用与内核进行交互&#xff0c;使用内核提供的各种功能和资源。…

刷代码随想录有感(99):动态规划——使用最小花费爬楼梯

题干&#xff1a; 代码&#xff1a; class Solution { public:int minCostClimbingStairs(vector<int>& cost) {vector<int>dp(cost.size() 1);dp[0] 0;dp[1] 0;for(int i 2; i < cost.size(); i){dp[i] min(dp[i - 1] cost[i - 1], dp[i - 2] cost…

Leetcode 力扣114. 二叉树展开为链表 (抖音号:708231408)

给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 示例 1&#xf…

KUKA机器人中断编程详细教程1—了解中断

在公众号查看更多内容。 在KUKA机器人编程与调试中&#xff0c;经常会用到中断编程。通过中断实现机器人暂停&#xff0c;或者停止当前的动作进入中断后的程序中接着运行&#xff0c;以此来满足实际的调试要求。 1、中断的概念 ①当出现诸如输入等定义的事件时&#xff0c;…

【算法篇】求最长公共前缀JavaScript版本

题目描述 给你一个大小为 n 的字符串数组 strs &#xff0c;其中包含n个字符串 , 编写一个函数来查找字符串数组中的最长公共前缀&#xff0c;返回这个公共前缀。 数据范围&#xff1a; 数据范围:0<n<5000&#xff0c;0<len(strsi)< 5000 进阶:空间复杂度 O(1)&a…

Typora Markdown编辑器 for Mac v1.8.10 安装

Mac分享吧 文章目录 效果一、准备工作二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2. 应用程序显示软件图标&#xff0c;表示安装成功 三、运行调试1、修改主题2、显示文档列表&#xff0c;如下图3、查看版本信息 **安装完成&…

【PR2019】怎样批量添加转场效果及修改默认持续时间

一&#xff0c;设置“交叉溶解”效果到所有素材 选择效果&#xff0c;右击“将所选过渡设置为默认过渡”&#xff1a; 框选所有素材&#xff0c;“Ctrl D”&#xff1a; 每个素材中间有有了交叉溶解的效果&#xff1a; 二&#xff0c;修改效果属性 2.1&#xff0c;单个修…