前言
学习 Unity 那么对于协程的学习也是必不可少。我们常常会使用协程实现异步加载场景,或者一个计时器,其作用强大,这里我将结合我的了解,来学习一番。
协程是什么
Unity 的协程是一个会暂停协程的任务,主线程去完成调用协程的函数的剩余代码,而每帧 Unity 都会去协程的 yield 检索其 return 条件,直到条件符合,将会执行 yield 的后续代码。
协程的结构用法
1 | otherMethod(){ |
其运行流程
otherMethod(){}
运行到StartCoroutine(test())
- 执行
test()
语句 到yield return new WaitForSenconds(2f)
则会返回,运行Debug.Log("This is remain code!")
语句 - 随后每帧都会判定 yield 的条件,也即是等待 2s
- 时间到达后,就会执行协程 yield 的后面语句
Debug.Log("I can do!")
- 如果要结束此协程则
StopCoroutine("test")
,即可
生命周期
与线程的区别
线程的特点是有自己独立的栈和共享的堆,线程由操作系统来调度。
协程与线程类似也有独立的栈和共享的堆,但是协程需要在线程中开启,其依赖 update 函数。
最主要区别在于:协程避免了无意义的调度,提高了性能,但是需要由程序员来担任调度协程的任务,这也使得协程无法像线程一样实现并行(当有多核cpu时,线程可以实现并行,使用多核性能,但是协程只能占用单核)
线程间的调度,是由操作系统来操作的,这可能会使两个线程来回切换,而协程是处理完事务后,就让权给其他协程。
另一个特点是,Unity 的线程线程只能进行与 Unity 无关的工作,而协程可以。往往 Unity 中线程被用来做与 Unity 无关的费时逻辑运算。
在一个MonoBehaviour提供的主线程里只能有一个处于运行状态的协程。因为协程不是线程,不是并行的。同一时刻、一个脚本实例中可以有多个暂停的协程,但只有一个运行着的协程。
协程的启动
- StartCoroutine(IEnumerator routine)
- StartCoroutine(string routine)或StartCoroutine(string routine,object value) 通过传入函数名字的字符串启动协程的性能开销要更高,但这种方式启动的协程可以通过StopCoroutine(string methondname)来终止,这种方式还有一个限制就是只能传递一个参数。
协程的关闭
- StopCoroutine(string methondname) 只能终止通过字符串名字启动的协程
- StopCoroutine(Coroutine coroutine)
- StopAllCoroutines() 终止所有协程
- 在协程内部终止可以使用
yeild break
- 可以使开启协程的物体的 active 设置为 false
协程的特点
一个协同程序在执行过程中,可以在任意位置使用yield语句。yield的返回值控制何时恢复协同程序向下执行。协同程序在对象自有帧执行过程中堪称优秀。协同程序在性能上没有更多的开销。
缺点是协同程序并非真线程,可能会发生堵塞。
迭代器
其实协程的本质是由迭代器实现的。
待续。。