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 分帧执行,改变图像颜色

img

4.2 定时器

img

4.3 异步下载

img

4.4 协同嵌套

img

4.5 创建互斥区

img

5.协程的使用误区

5.1 协程的使用一定是在一个实现Monobehaviour接口的类中的;

5.2 当这个脚本被disable或者destroy,协程会被终止;

5.3 为了逻辑清晰,尽量不要用stop coroutine ;

5.4 不要滥用协程,这个不是容易读懂的代码;

6.参考

(22条消息) Unity-协程详解_卖烤麸烤饼儿的博客-CSDN博客_unity协程

最后修改:2023 年 11 月 12 日
如果觉得我的文章对你有用,请随意赞赏