【Unity入门】协程(IEnumerator)的使用方法介绍

目录

  • 一、前言:
  • 二、关于协程
    • 1、什么是协程
    • 2、协程的原理
  • 三、协程的使用
    • 1、函数的方式
    • 2、函数名的方式
    • 3、接收返回值
    • 4、StopAllCoroutines
    • 5、禁用/销毁游戏对象
    • 6、yield return的介绍:
  • 四、小结:

一、前言:

协程在Unity中是一个很重要的概念,我们知道,在使用Unity进行游戏开发时,一般(注意是一般)不考虑多线程,那么如何处理一些在主任务之外的需求呢,Unity给我们提供了协程这种方式。

为啥在Unity中一般不考虑多线程?
因为在Unity中,只能在主线程中获取物体的组件、方法、对象,如果脱离这些,Unity的很多功能无法实现,那么多线程的存在与否意义就不大了。

线程与协程有什么区别?
对于协程而言,同一时间只能执行一个协程,而线程则是并发的,可以同时有多个线程在运行
两者在内存的使用上是相同的,共享堆,不共享栈
其实对于两者最关键,最简单的区别是微观上线程是并行(对于多核CPU)的,而协程是串行的,如果你不理解没有关系,通过下面的解释你就明白了

二、关于协程

1、什么是协程

协程,从字面意义上理解就是协助程序的意思,我们在主任务进行的同时,需要一些分支任务配合工作来达到最终的效果,稍微形象的解释一下,想象一下,在进行主任务的过程中我们需要一个对资源消耗极大的操作时候,如果在一帧中实现这样的操作,游戏就会变得十分卡顿,这个时候,我们就可以通过协程,在一定帧内完成该工作的处理,同时不影响主任务的进行。

2、协程的原理

首先需要了解协程不是线程,协程依旧是在主线程中进行,然后要知道协程是通过迭代器来实现功能的,通过关键字IEnumerator来定义一个迭代方法,注意使用的是IEnumerator,而不是IEnumerable。
两者之间的区别:
IEnumerator:是一个实现迭代器功能的接口
IEnumerable:是在IEnumerator基础上的一个封装接口,有一个GetEnumerator()方法返回IEnumerator
在迭代器中呢,最关键的是yield 的使用,这是实现我们协程功能的主要途径,通过该关键方法,可以使得协程的运行暂停、记录下一次启动的时间与位置等等。
关于迭代器的具体解释可以参考:C#官方文档关于迭代器的具体描述。

三、协程的使用

错误理解:
如果一个协程几乎每帧都运行并且在长时间运行操作中不会暂停,那么用 Update 或 LateUpdate 回调来替换该协程通常更合理一些。例如长时间运行或无限循环的协程。
尽可能的减少嵌套使用:虽然嵌套的协程非常有利于确保代码的条理性和进行维护,但协程跟踪对象本身会导致产生更高的内存开销。

1、函数的方式

使用传递函数的方式来 开启协程:

StartCoroutine(Cor_1());

停止协程:(❎ 错误的使用方式1)

StopCoroutine(Cor_1());

最初学习的时候就这么干的,但是不知道为什么就是不好用。后来才明白:虽然传递的是一样的函数名,但是停止时传递进去的并不是开始时传递的函数的地址啊~。

停止协程:(❎ 错误的使用方式2)

StopCoroutine(”Cor_1“);

新手的错误用法:使用传递函数的方式开启协程,使用传递字符串的形式停止协程。

那么使用StartCoroutine(Cor_1());这种方式开启协程,要如何才能手动停掉它呢?请继续往下看…

2、函数名的方式

使用传递函数名的方式 开启协程:

StartCoroutine("Cor_1");

停止协程:

StopCoroutine(”Cor_1“);

这样使用是没问题的(我猜测是内部是实现是通过<Key, Value>的形式保存了一下)。

缺点:只支持传递一个参数。

由一,二得出结论,只有通过函数名的形式开启和关闭是可行的,但是这并没有解决我们方式一中留下的问题,请继续往下看吧…

3、接收返回值

不管使用下面哪种方式启动协程,都可以结束其返回值用以停止对应协程;

private Coroutine stopCor_1;
private Coroutine stopCor_2;stopCor_1 = StartCoroutine("Cor_1");
stopCor_2 = StartCoroutine(Cor_2());

停止协程:

StopCoroutine(stopCor_1);
StopCoroutine(stopCor_2); 

使用这种接收返回值的方式就可以根据我们的需求来停止协程了;
这就解决了方式一,二中留下的问题。

4、StopAllCoroutines

任意一种方式开始协程

StartCoroutine("Cor_1");
StartCoroutine(Cor_2());

都可以使用StopAllCoroutines去停止

StopAllCoroutines();

StopAllCoroutines() 可以停止当前脚本中所有协程。

注意事项:

建议谨慎使用,因为可能后续修改逻辑时新建协程,在不需要被停止的情况下停止(别问我怎么知道的)
需要确定调用脚本的全部协程都需要被终止(比如:断线重连需要重置所有状态)

5、禁用/销毁游戏对象

禁用/销毁游戏对象 协程会停止。当物体被再次激活时,协程不会继续执行。

gameObject.SetActive(false); 
//通过销毁游戏对象方式和禁用同效果
//Destroy(gameobject)

不是这个:

script.enabled = false; 

也就是隐藏脚本所挂载的游戏物体(其父物体被隐藏时也是一样)。

6、yield return的介绍:

yield return null; // 下一帧再执行后续代码
yield return 0; //下一帧再执行后续代码
yield return 6;//(任意数字) 下一帧再执行后续代码
yield break; //直接结束该协程的后续操作
yield return asyncOperation;//等异步操作结束后再执行后续代码
yield return StartCoroution(/*某个协程*/);//等待某个协程执行完毕后再执行后续代码
yield return WWW();//等待WWW操作完成后再执行后续代码
yield return new WaitForEndOfFrame();//等待帧结束,等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前执行
yield return new WaitForSeconds(0.3f);//等待0.3秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间会受到Time.timeScale的影响);
yield return new WaitForSecondsRealtime(0.3f);//等待0.3秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间不受到Time.timeScale的影响);
yield return WaitForFixedUpdate();//等待下一次FixedUpdate开始时再执行后续代码
yield return new WaitUntil()//将协同执行直到 当输入的参数(或者委托)为true的时候....如:yield return new WaitUntil(() => frame >= 10);
yield return new WaitWhile()//将协同执行直到 当输入的参数(或者委托)为false的时候.... 如:yield return new WaitWhile(() => frame < 10);

四、小结:

  1. 使用 StartCoroutine(函数()); 形式开启的,只能用接收返回值的形式去停止;【不限制参数个数】
  2. 使用 StartCoroutine(“函数名”); 形式开启的,可以使用 StopCoroutine(“函数名”); 形式停止, 也可使用 接收返回值的形式去停止。【缺点:只可以传递一个参数】
  3. 两种开启形式均受到 StopAllCoroutines() 控制。StopAllCoroutines() 可以停止当前脚本中所有协程。
  4. gameObject.SetActive(false); 可停掉所有此GameObject上的所有协程,且再次激活时协程不会继续。
  5. StopCoroutine(函数()); 脚本.enabled = false; 不可停掉协程。

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

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

相关文章

人机协同是虚拟与真实的协同

“人机协同”是指人类与机器之间的合作与协同工作。在这种协同中&#xff0c;机器可以作为助手、辅助或扩展人类的能力&#xff0c;帮助人们完成任务&#xff0c;提高工作效率和质量。 虚拟与真实的协同是指在人机协同的过程中&#xff0c;虚拟想象世界和真实世界之间的协同。通…

【Spring】Springmvc学习Ⅲ

# Spring&#xff4d;vc学习Ⅲ 文章目录 一、图书管理系统1. 功能1.1 登录前端接口前端代码后端接口后端代码 1.2 图书列表展示步骤:图书类代码mock数据代码控制层调用代码服务层代码&#xff08;存储除数据库中需要存储的数据&#xff09; 2. 分层控制2.1 三层架构2.2 代码重…

缓存一致性

缓存数据一致性 双写模式失效模式 都会导致缓存不一致问题。 解决方案-Canal 更新 DB 会产生的 binlog&#xff0c;Canal 订阅 binlog&#xff0c;监测到数据库的更新&#xff0c;从而更新缓存。 解决方案-分布式读写锁 适用于读多写少的情况

【数据结构】-- 相交链表-环形链表

交叉链表 . - 力扣&#xff08;LeetCode&#xff09; 如果链表的两条链的长度一样&#xff0c;链表两端对齐&#xff0c;解决这个问题将会变得非常简单&#xff0c;直接分别遍历两个链表&#xff0c;想等时的节点即为所求。我们想办法让链表对齐--分别从a和b遍历链表&#xff…

Mysql与Java连接----JDBC

前言: 当将Java与MySQL数据库连接时&#xff0c;JDBC&#xff08;Java Database Connectivity&#xff09;是一种重要的技术。JDBC允许Java应用程序通过标准的数据库访问方式与不同的关系型数据库进行通信&#xff0c;其中包括MySQL。通过使用JDBC&#xff0c;Java开发人员可以…

二叉树的前序、中序、后序遍历

二叉树的前序、中序、后序 1.二叉树的前序遍历 题目&#xff1a; 二叉树的前序遍历 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3]示例 2&#xff1a; 输入&#xff…

aigc的基础知识介绍

AIGC,即人工智能生成内容(Artificial Intelligence Generated Content),是一种利用人工智能技术自动生成各种形式内容的技术。以下是关于AIGC的基础知识介绍: 定义:AIGC指的是利用人工智能技术和算法来自动生成各种形式的内容,如文本、图像、音频和视频等。 发展历程:A…

LeetCode题练习与总结:不同的二叉搜索树Ⅱ--95

一、题目描述 给你一个整数 n &#xff0c;请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,nul…

Unity自定义动画-Animation动画数据-How is “fileIDToRecycleName“ generated

一般美术和程序分工明确的项目 fbx确实是和动画一一对应的&#xff1b; 但一些独立&#xff0c;或者小工作室的项目&#xff0c;就没法保证了&#xff0c;关键还是在于 Unity的 .meta 目录 查找和对比了一下 .fbx 和 .meta&#xff1a; 缓存和不缓存Animation 具体的Animat…

HCIP-Datacom-ARST自选题库_03_VLAN【26道题】

一、单选题 1.QinQ技术是一项扩展VLAN空间的技术&#xff0c;通过在802.1Q标签报文的基础上再增加一层802.1Q的Tag来达到扩展VLAN空间的功能。下列关于QinQ说法错误的是 灵活QinQ可以根据不同的内层Tag而加上不同的外层Tag&#xff0c;对于用户VLAN的划分更加细致 QinQ使VLA…

Golang | Leetcode Golang题解之第86题分隔链表

题目&#xff1a; 题解&#xff1a; func partition(head *ListNode, x int) *ListNode {small : &ListNode{}smallHead : smalllarge : &ListNode{}largeHead : largefor head ! nil {if head.Val < x {small.Next headsmall small.Next} else {large.Next hea…

栈的详尽技术分析

栈的详尽技术分析 一、引言 在计算机科学的领域中&#xff0c;数据结构是组织和管理数据的方式&#xff0c;对于编写高效算法而言至关重要。栈作为一种特殊的数据结构&#xff0c;其应用广泛&#xff0c;对理解程序语言的编译、内存管理以及算法设计等方面都有重要意义。 二、栈…

ue引擎游戏开发笔记(39)——npc的ai设定:追踪玩家以及瞄准

1.需求分析&#xff1a; 实现对npc的击杀和死亡反馈后&#xff0c;下一步需要赋予npc基本的ai&#xff0c;首先就是敌人要能够追踪或者说跟随玩家&#xff0c;这才能为后续npc开枪&#xff0c;对射做好准备&#xff0c;首先实现追踪玩家。 2.操作实现&#xff1a; 1.思路&…

代码随想录第六天打卡|242.有效的字母异位词,349. 两个数组的交集,202. 快乐数

242.有效的字母异位词 Python from collections import Counter class Solution:def isAnagram(self, s: str, t: str) -> bool:nCounter(s)mCounter(t)return nm C class Solution { public:bool isAnagram(string s, string t) {int Map[26]{0};for (int i0;i<s.s…

数据结构填空题专项.docx

1. 根据数据元素间关系的不同特性&#xff0c;通常可分为集合、线性 、树形 、图状 四 类基本结构。 2. 算法的 5 个特征包括&#xff1a; 有穷性、确定性 、有效性、输入和输出。 3. 数据结构中的数据元素存在“一对多”的关系称为 树形 结构。 4. 在包含 n 个元素的…

2024.5组队学习——MetaGPT智能体理论与实战(待续)

学习资料&#xff1a;项目地址——hugging-multi-agent、在线阅读、MetaGPT项目、MetaGPT中文文档 文章目录 一、环境配置1.1 配置MetaGPT1.2 配置大模型api_key1.3 测试demo 一、环境配置 全部工作在Autodl上完成&#xff0c;下面是简单记录&#xff1a; 1.1 配置MetaGPT 下…

不好!有敌情,遭到XSS攻击【网络安全篇】

XSS&#xff1a;当一个目标的站点&#xff0c;被我们用户去访问&#xff0c;在渲染HTMl的过程中&#xff0c;出现了没有预期到的脚本指令&#xff0c;然后就会执行攻击者用各种方法注入并执行的恶意脚本&#xff0c;这个时候就会产生XSS。 涉及方&#xff1a; 用户&#xff0…

前端铺子-uniapp移动端:跨平台开发新篇章

一、引言 在移动应用开发领域&#xff0c;随着技术的不断进步&#xff0c;用户对应用的需求也日益多样化。如何快速、高效地开发跨平台应用成为了前端开发者面临的一大挑战。uni-app作为一款使用Vue.js开发所有前端应用的框架&#xff0c;凭借其一次编写、多端运行的特性&…

Vue Excel 文件流导出乱码快速解决方案

今日在开发一个导出功能&#xff0c;原本一个非常简单的功能&#xff0c;却没想里面藏了陷阱&#xff01; 背景 前端导出的文件流乱码&#xff0c;此时确定非后端问题&#xff08;可以在postman导出是否正常来判断&#xff09;。 前端导出&#xff1a; 后端正常数据&#xf…

Nature 综述(IF=88):微生物群落和土壤性质之间的相互作用

随着社会的发展&#xff0c;环境污染和自然资源的消耗日益严重&#xff0c;土壤生态系统的健康状况备受关注。然而&#xff0c;当前研究领域存在一个问题&#xff0c;即在研究土壤微生物群落结构的同时&#xff0c;忽略了微生物对土壤环境的影响。本文旨在探讨微生物如何通过生…