Unity协程总结
1.协程介绍
unity的协程(Coroutine)只是在c#的基础上做了一层封装,其实yield是C#的关键字。
unity协程是一个能够暂停协程执行,暂停后立即返回主函数,执行主函数剩余的部分,直到中断指令完成后,从中断指令的下一行继续执行协程剩余的函数。
函数体全部执行完成,协程结束。
由于中断指令的出现,使得可以将一个函数分割到多个帧里去执行。
协程不是进程,也不是线程,它就是一个特殊的函数——可以在某个地方挂起,并且可以重新在挂起处继续运行。
1.1 协程方法与普通方法的区别:
1.1.1 普通方法
被调用时,原来执行的部分保留现场,停止执行,然后去执行要调用的方法,并且,被调用的方法执行完之后才能返回到调用前的状态接着往下执行。
1.1.2 协同方法
执行不用等协同方法执行完再执行调用之前原来方法的代码,而是两者异步执行。
协程不是多线程,它与主线程同时运行,它在主线程运行的同时开启另一段逻辑处理。
类似一个子线程单独出来处理一些问题,性能开销较小。
Unity的协程会在每帧结束之后去检测yield的条件是否满足,满足则执行yield return之后的代码。
**在一个MonoBehaviour提供的主线程里只能有一个处于运行状态的协程,而其他协程处于休眠状态。
协程实际上是在一个线程中,只不过每个协程对CUP进行分时,协程可以访问和使用unity的所有方法和component。**
1.2 性能
在性能上相比于一般函数没有更多的开销
1.3 协程的好处
让原来要使用异步 + 回调方式写的非人类代码, 可以用看似同步的方式写出来。
能够分步做一个比较耗时的事情,如果需要大量的计算,将计算放到一个随时间进行的协程来处理,能分散计算压力
1.4 协程的坏处:
协程本质是迭代器,且是基于unity生命周期的,大量开启协程会引起GC(Garbage Collection垃圾回收)
如果同时激活的协程较多,就可能会出现多个高开销的协程挤在同一帧执行导致的卡帧
1.5 协程书写时的性能优化:
常见的问题是直接new 一个中断指令,带来不必要的 GC 负担,可以复用一个全局的中断指令对象,优化掉开销;
这个链接分析了一下Unity 协程运行时的监控和优化 - 知乎 (zhihu.com)
1.6 协程是在什么地方执行?
协程不是线程,不是异步执行;协程和monobehaviour的update函数一样也是在主线程中执行
unity在每一帧都会处理对象上的协程,也就是说,协程跟update一样都是unity每帧会去处理的函数
经过测试,协程至少是每帧的lateUpdate后运行的。
参照unity的生命周期图
以上摘自(22条消息) Unity-协程详解_卖烤麸烤饼儿的博客-CSDN博客_unity协程
1.协程的基本使用方法
Start()
{
StartCoroutine(xiecheng());//开始协程
}
//定义协程
IEnumerator xiecheng()
{
//Coroutine操作,不同返回代表着不同意义
yield return null;
}
2.协程的Coroutine操作
yield return的常见返回值及其作用:
- yield return new WaitForSeconds(3.0f); // 等待3秒,然后继续从此 处开始,常用于做定时器。
- yield return null; // 这一帧到此暂停,下一帧再从暂停处继续,常用于循环中。
- yield return 1; // 这一帧到此暂停,下一帧再从暂停处继续。这里return什么都是等一帧,后面的返回值没有特殊意义。所以返回0或1或100都是一样的。参考:http://blog.csdn.net/nanggong/article/details/48421053
- yield return new WaitForEndOfFrame(); // 等到这一帧的cameras和GUI渲染结束后再从此处继续,即等到这帧的末尾再往下运行。这行之后的代码还是在当前帧运行,是在下一帧开始前执行,跟return null很相似。
- yield return new WaitForFixedUpdate(); // 在下一次执行FixedUpdate的时候继续执行这段代码,即等一次物理引擎的更新。
- yield return www; // 等待直至异步下载完成。
- yield break; // 直接跳出协程,对某些判定失败必须跳出的时候,比如加载AssetBundle的时候,WWW失败了,后边加载bundle没有必要了,这时候可以yield break跳出。
- yield return StartCoroutine(methodName); // 等待另一个协程执行完。这是把协程串联起来的关键,常用于让多个协程按顺序逐个运行。
更多关于Yield的研究与实验:http://blog.csdn.net/huang9012/article/details/29595747
3.协程的效率
一个什么也不做的协程也至少需要等待一帧来完成(激活后下一帧才开始)
4.协程的实际应用
4.1 分帧执行,改变图像颜色
4.2 定时器
4.3 异步下载
4.4 协同嵌套
4.5 创建互斥区
5.协程的使用误区
5.1 协程的使用一定是在一个实现Monobehaviour接口的类中的;
5.2 当这个脚本被disable或者destroy,协程会被终止;
5.3 为了逻辑清晰,尽量不要用stop coroutine ;
5.4 不要滥用协程,这个不是容易读懂的代码;