0%

Unity-探索协程

前言

学习 Unity 那么对于协程的学习也是必不可少。我们常常会使用协程实现异步加载场景,或者一个计时器,其作用强大,这里我将结合我的了解,来学习一番。

协程是什么

Unity 的协程是一个会暂停协程的任务,主线程去完成调用协程的函数的剩余代码,而每帧 Unity 都会去协程的 yield 检索其 return 条件,直到条件符合,将会执行 yield 的后续代码。

协程的结构用法

1
2
3
4
5
6
7
8
9
10
11
12
otherMethod(){
...
StartCoroutine(test());
Debug.Log("This is remain code!");
}

// 迭代器
IEnumerator test(){
...
yield return new WaitForSenconds(2f); // 暂停两秒
Debug.Log("I can do!");
}

其运行流程

  1. otherMethod(){} 运行到 StartCoroutine(test())
  2. 执行 test() 语句 到 yield return new WaitForSenconds(2f) 则会返回,运行 Debug.Log("This is remain code!") 语句
  3. 随后每帧都会判定 yield 的条件,也即是等待 2s
  4. 时间到达后,就会执行协程 yield 的后面语句 Debug.Log("I can do!")
  5. 如果要结束此协程则 StopCoroutine("test") ,即可

生命周期

1

与线程的区别

线程的特点是有自己独立的栈和共享的堆,线程由操作系统来调度。

协程与线程类似也有独立的栈和共享的堆,但是协程需要在线程中开启,其依赖 update 函数。

最主要区别在于:协程避免了无意义的调度,提高了性能,但是需要由程序员来担任调度协程的任务,这也使得协程无法像线程一样实现并行(当有多核cpu时,线程可以实现并行,使用多核性能,但是协程只能占用单核)

线程间的调度,是由操作系统来操作的,这可能会使两个线程来回切换,而协程是处理完事务后,就让权给其他协程。

另一个特点是,Unity 的线程线程只能进行与 Unity 无关的工作,而协程可以。往往 Unity 中线程被用来做与 Unity 无关的费时逻辑运算。

在一个MonoBehaviour提供的主线程里只能有一个处于运行状态的协程。因为协程不是线程,不是并行的。同一时刻、一个脚本实例中可以有多个暂停的协程,但只有一个运行着的协程。

协程的启动

  1. StartCoroutine(IEnumerator routine)
  2. StartCoroutine(string routine)或StartCoroutine(string routine,object value) 通过传入函数名字的字符串启动协程的性能开销要更高,但这种方式启动的协程可以通过StopCoroutine(string methondname)来终止,这种方式还有一个限制就是只能传递一个参数。

协程的关闭

  1. StopCoroutine(string methondname) 只能终止通过字符串名字启动的协程
  2. StopCoroutine(Coroutine coroutine)
  3. StopAllCoroutines() 终止所有协程
  4. 在协程内部终止可以使用 yeild break
  5. 可以使开启协程的物体的 active 设置为 false

协程的特点

一个协同程序在执行过程中,可以在任意位置使用yield语句。yield的返回值控制何时恢复协同程序向下执行。协同程序在对象自有帧执行过程中堪称优秀。协同程序在性能上没有更多的开销。
缺点是协同程序并非真线程,可能会发生堵塞。

迭代器

其实协程的本质是由迭代器实现的。
待续。。