Unity 协程(Coroutine)原理与用法详解

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

为啥在Unity中一般不考虑多线程

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

既然这样,线程与协程有什么区别呢:

对于协程而言,同一时间只能执行一个协程,而线程则是并发的,可以同时有多个线程在运行

两者在内存的使用上是相同的,共享堆,不共享栈

其实对于两者最关键,最简单的区别是微观上线程是并行的,而协程是串行的,如果你不理解没有关系,通过下面的解释你就明白了

关于协程 1,什么是协程

协程,从字面意义上理解就是协助程序的意思,我们在主任务进行的同时,需要一些分支任务配合工作来达到最终的效果

稍微形象的解释一下,想象一下,在进行主任务的过程中我们需要一个对资源消耗极大的操作时候,如果在一帧中实现这样的操作,游戏就会变得十分卡顿,这个时候,我们就可以通过协程,在一定帧内完成该工作的处理,同时不影响主任务的进行

2,协程的原理

首先需要了解协程不是线程,协程依旧是在主线程中进行

然后要知道协程是通过迭代器来实现功能的,通过关键字IEnumerator来定义一个迭代方法,注意使用的是IEnumerator,而不是IEnumerable:

两者之间的区别:

IEnumerator:是非泛型的,也是协程认可的参数

IEnumerable:通过泛型实现的迭代器,协程不使用该迭代器

在迭代器中呢,最关键的是yield 的使用,这是实现我们协程功能的主要途径,通过该关键方法,可以使得协程的运行暂停、记录下一次启动的时间与位置等等:

关于迭代器的具体解释:

可以参考:C#官方文档关于迭代器的具体描述

由于yield 在协程中的特殊性,与关键性,我们到后面在单独解释,先介绍一下协程如何通过代码实现

3、协程的使用

首先通过一个迭代器定义一个返回值为IEnumerator的方法,然后再程序中通过StartCoroutine来开启一个协程即可:

在正式开始代码之前,需要了解StartCoroutine的两种重载方式:

StartCoroutine(string methodName:这种是没有参数的情况,直接通过方法名(字符串形式)来开启协程

StartCoroutine(IEnumerator routine:通过方法形式调用

StartCoroutine(string methodName,object values):带参数的通过方法名进行调用

协程开启的方式主要是上面的三种形式,如果你还是不理解,可以查看下面代码:

//通过迭代器定义一个方法 IEnumerator Demo(int i) { //代码块 yield return 0; //代码块 } //在程序种调用协程 public void Test() { //第一种与第二种调用方式,通过方法名与参数调用 StartCoroutine("Demo", 1); //第三种调用方式, 通过调用方法直接调用 StartCoroutine(Demo(1)); }

在一个协程开始后,同样会对应一个结束协程的方法StopCoroutine与StopAllCoroutines两种方式,但是需要注意的是,两者的使用需要遵循一定的规则,在介绍规则之前,同样介绍一下关于StopCoroutine重载:

StopCoroutine(string methodName:通过方法名(字符串)来进行

StopCoroutine(IEnumerator routine:通过方法形式来调用

StopCoroutine(Coroutine routine):通过指定的协程来关闭

刚刚我们说到他们的使用是有一定的规则的,那么规则是什么呢,答案是前两种结束协程方法的使用上,如果我们是使用StartCoroutine(string methodName)来开启一个协程的,那么结束协程就只能使用StopCoroutine(string methodName)和StopCoroutine(Coroutine routine)来结束协程,可以在文档中找到这句话:

在这里插入图片描述

4、关于yield

在上面,我们已经知道yield 的关键性,要想理解协程,就要理解yield

如果你了解Unity的脚本的生命周期,你一定对yield 这几个关键词很熟悉,没错,yield 也是脚本生命周期的一些执行方法,不同的yield 的方法处于生命周期的不同位置,可以通过下图查看:

在这里插入图片描述


通过这张图可以看出大部分yield位置Update与LateUpdate之间,而一些特殊的则分布在其他位置,这些yield 代表什么意思呢,又为啥位于这个位置呢

首先解释一下位于Update与LateUpdate之间这些yield 的含义:

yield return null; 暂停协程等待下一帧继续执行

yield return 0或其他数字; 暂停协程等待下一帧继续执行

yield return new WairForSeconds(时间); 等待规定时间后继续执行

yield return StartCoroutine("协程方法名");开启一个协程(嵌套协程)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjszy.html