文章目录
- 前言
- 协程的概念
- 协程的使用
-
- 协程方法的声明
- 协程的启用
- 协程的停止
- 小结
前言
我们知道,Unity中的代码是大致上是按帧循环执行,一般的一个方法中的逻辑是会在一帧内执行完毕的,那么如果我们需要将某段代码延时进行执行的时候该怎么办呢?
当然,我们可以自己设置一个计时器变量,每帧更新,在合适的时候再进行代码块的执行,这样处理毫无疑问是可以的,但如果需要进行计时的对象数量很多的时候,这样处理就不免会变得麻烦起来了,那有没有什么简单的方法可以实现这个需求呢?
Coroutine(协程)就可以很简单的解决这个问题。
协程的概念
要理解协程,首先就得先明白线程和进程的概念:
进程:系统进行资源分配的基本单位,通俗地来说就是一个又一个的应用程序;
线程:是进程的组成单位,它一条条顺序的命令执行流,所以也可以看做是系统进行命令执行和资源分配的最小单位
为了辅助理解,让我们来看看Win10的资源监视器:
系统进行了内存分配的这些exe,就是进程,而他们又由一条条线程组成,一条线程又由复数的代码块组成执行逻辑命令
单个线程是顺序执行的,很显然我们并不会只有线性的需求,当我们需要多个任务同时执行的时候,多线程这一概念就出现了
而协程则是C#中用于实现“多线程”的一种“伪多线程”操作
先让我们来个简单的协程,来初步看看协程的效果:
public class SimpleCoroutine : MonoBehaviour
{
private int count = 0;
void Start()
{
StartCoroutine(CoroutineTest());
}
void Update()
{
count += 1;
print("Count : " + count);
}
IEnumerator CoroutineTest()
{
for (int i = 0; i < 5 ;i++ )
{
print("i : " + i);
yield return null;
}
}
}
来分析一下这段代码,
首先声明了一个全局变量count,它的初始值为0,并在Updata()方法中进行每帧自增自身的值1,和在控制台打印它的值
声明了一个使用了协程的方法CoroutineTest(),它会在for循环的i值小于5之前,每当i自增1就打印一次i的值,它在脚本的Start()方法中进行了启动
这个脚本执行后的结果如下:
可以看到,i的值与Count的值在交替打印
如果按照正常的线性顺序来看的话,在Start方法中进行了启动的CoroutineTest方法应该先于打印第一个Count之前就已经完成了所有的打印,而现在如上图的交替打印结果就是协程实现的效果了——它使得CoroutineTest方法中的for循环中的内容进行了一个逐帧的延时。
协程的使用
协程方法的声明
就像上一部分的例子中声明CorotineTest()的方式一样
要将一个代码块使用协程进行处理,首先需要使它所在的方法的返还为一个IEnumerator类型
因为协程实际上就是通过迭代器实现的,底层的东西这里就不做过多讨论了
然后需要做的事是在你希望它进行暂时中断的地方加上一条yield return语句,返还的值为非YieldInstruction类的子类的任意值(推荐使用null、1或0)时,它的效果都是延时一帧
而YieldInstruction类的子类则包含有如下几种:
效果从名字上可以很明显的看得出来,不一一赘述
比较常用的是WaitForSeconds类:
yield return new WaitForSeconds(float seconds);
按照这样的形式进行返还即可,float类型的seconds参数决定了中断的时长,以秒为单位
协程的启用
启用一个协程使用的是封装在Behaviour类中的StartCoroutine()方法,它有如下两种重载:
StartCoroutine(string methodName);
StartCoroutine(IEnumerator routine);
第一种是使用string类型的方法名作为参数
第二种则是直接接收目标方法返还的IEnumerator类型
但是我们注意到,这样调用方法并没有带有参数,那么启用一个需要使用到参数的方法要怎么实现呢?
在使用string类型的作为参数的StartCoroutine()方法中还有这么一种重载:
StartCoroutine(string methodName, [DefaultValue(“null”)] object value);
默认值为null的参数value会作为目标方法的参数参与启用协程
协程的停止
很自然地,有启动便有停止——StopCoroutine()方法,它也被封装在封装于Behaviour类中,重载方式主要也是如下的两种:
StopCoroutine(IEnumerator routine)
StopCoroutine(string methodName)
但要注意的是,它只能用于停止那些使用string类型参数的启用方式进行启用的方法
小结
协程的主要作用就是对一个代码块的执行进行延时,所以它的常用场景是在需要实现一个简单的计时器,或者对大量计算进行延时处理的时候