[Unity]Unity中的协程
Unity中的协程
协程的基础
-
协程 是用户态的轻量级线程,线程内部调度的基本单位,拥有自己的寄存器上下文和栈。
-
同一时间只能执行一个协程,而其他协程处于休眠状态,适合对任务进行分时处理。对于 Unity 来说协程是单线程的,在主线程中完成。
-
切换时先将寄存器上下文和栈保存,等切换回来的时候再进行恢复。也就是说协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。由于直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
协程的使用
协程就像一个函数,能够暂停执行并将控制权返还给 Unity,然后在达到条件时被挂起,继续执行后面的部分。
- 挂起协程
1 | public Coroutine StartCoroutine(IEnumerator routine) |
- 终止协程
1 | public void StopCoroutine(IEnumerator routine); |
协程的原理
IEnumerator
协程的本质是一个 IEnumerator (迭代器)。
1 | public interface IEnumerator |
Unity 在每帧做的工作就是:调用 IEnumerator
的 MoveNext()
方法,如果返回 true
,就从当前位置继续往下执行;如果是返回 false
,就是结束迭代器。
Yield
yield
的本质是语法糖,通过实现 IEnumerator
来实现迭代功能。
在协程中使用 yield return
会返回一个 IEnumerator
对象。
Unity 每帧调用这个 IEnumerator
对象的 MoveNext()
方法。
当这个 IEnumerator
对象的 MoveNext()
返回 false
时(也就是说这个 IEnumertator
的 Current
已经迭代到最后一个元素),Unity 就会将这个 IEnumerator
从 Cortoutines list 中移除。
移除了这个 IEnumerator
对象,也就可以接着执行后面的语句了(也就是 yield return
后面的语句)。
Unity 中实现了一个 YieldInstruction,是所有 yield
指令的基类。本质上也可以看作一个函数体,每帧 MoveNext()
检查是否返回 false
。
举个例子:
yield retrun new WaitForSeconds(2f);
等价于实现了一个这样的 MoveNext()
方法:
1 | private float elapsedTime; |
yield 的使用:
1 | yield return null / 0 / 任意数字; |
协程的生命周期
协程虽然是在 MonoBehvaviour 中经过 StartCoroutine 挂起的,但是 协程 与 MonoBehaviour 是一等级的,不受 MonoBehaviour 的状态影响;但协程与 MonoBehaviour 一样受到 GameObject 的控制。
也就是说:在某一个 MonoBehavior 中的协程在执行时,若将该 MonoBehavior .enabled = false
,协程并不会停止;但将挂载该 MonoBehavior 的 GameObject SetActive(false)
,协程就会停止。
参考
Unity协程(Coroutine)原理深入剖析:https://www.cnblogs.com/123ing/p/3704949.html
Unity协程(Coroutine)原理深入剖析再续:https://www.cnblogs.com/123ing/p/3704947.html
c# yield关键字原理详解:https://www.cnblogs.com/blueberryzzz/p/8678700.html#undefined