unity协程理解

什么是协程?

unity协程是一个能够暂停协程执行,暂停后立即返回主函数,执行主函数剩余的部分,直到中断指令完成后,从中断指令的下一行继续执行协程剩余的函数。函数体全部执行完成,协程结束。

由于中断指令的出现,使得可以将一个函数分割到多个帧里去执行。

协程的好处:

让原来要使用异步 + 回调方式写的非人类代码, 可以用看似同步的方式写出来。

能够分步做一个比较耗时的事情,如果需要大量的计算,将计算放到一个随时间进行的协程来处理,能分散计算压力

协程的坏处:

协程本质是迭代器,且是基于unity生命周期的,大量开启协程会引起gc

如果同时激活的协程较多,就可能会出现多个高开销的协程挤在同一帧执行导致的卡帧

协程书写时的性能优化:

常见的问题是直接new 一个中断指令,带来不必要的 GC 负担,可以复用一个全局的中断指令对象,优化掉开销。

协程是在什么地方执行?

协程是通过迭代器来实现功能的,在迭代器中,最关键的是yield 的使用,这是实现协程功能的主要途径,通过该关键方法,可以使得协程的运行暂停、记录下一次启动的时间与位置。

在这里插入图片描述

yield 也是脚本生命周期的一些执行方法,不同的yield 的方法处于生命周期的不同位置:

yield return null; 暂停协程等待下一帧继续执行

yield return 0或其他数字; 暂停协程等待下一帧继续执行

yield return new WairForSeconds(时间); 等待规定时间后继续执行

yield return StartCoroutine(“协程方法名”);开启一个协程(嵌套协程)

yield return GameObject; 当游戏对象被获取到之后执行

yield return new WaitForFixedUpdate():等到下一个固定帧数更新

yield return new WaitForEndOfFrame():等到所有相机画面被渲染完毕后更新

yield break; 跳出协程对应方法,其后面的代码不会被执行

yield return new WaitUntil(…)根据定义挂起语句, 直到指定的条件返回 true

yield return new WaitWhile(…)根据定义挂起语句, 直到指定的条件返回 false

协程怎么开始?

首先通过一个迭代器定义一个返回值为IEnumerator的方法,然后再程序中通过StartCoroutine来开启一个协程即可:

在正式开始代码之前,需要了解StartCoroutine的两种重载方式:

StartCoroutine(string methodName):这种是没有参数的情况,直接通过方法名(字符串形式)来开启协程

StartCoroutine(IEnumerator routine):通过方法形式调用,方法可以带参数

StartCoroutine(string methodName,object values):带参数的通过方法名(字符串形式)+参数(参数类型而不是字符串)进行调用

协程怎么结束?

StopCoroutine(string methodName):通过方法名(字符串)来进行

注意事项:如果使用StartCoroutine(string methodName)来开启一个协程的,那么结束协程就只能使用StopCoroutine(string methodName)和StopCoroutine(Coroutine routine)来结束协程

StopCoroutine(IEnumerator routine):通过方法形式来调用

StopCoroutine(Coroutine routine):通过指定的协程来关闭

StopAllCoroutines暂停的是当前脚本下的所有协程

gameObject.active = false 可以停止该对象上全部协程的执行,即使再次激活,也不能继续执行。但注意MonoBehaviour enabled = false 不能停止协程;对比 update却是可以在MonoBehaviour enabled = false 就中止

原因:由于协程在StartCoroutine时被注册到的GameObject上,他的生命期受限于GameObject的生命期,因此受GameObject是否active的影响。

结论:协程虽然是在MonoBehvaviour启动的(StartCoroutine)但是协程函数的地位完全是跟MonoBehaviour是一个层次的,不受MonoBehaviour的状态影响。

协程结束的标志是什么?

如果最后一个 yield return 的 IEnumerator 已经迭代到最后一个是,MoveNext 就会 返回 false 。这时,Unity就会将这个 IEnumerator 从 cortoutines list 中移除。

只有当这个对象的 MoveNext() 返回 false 时,即该 IEnumertator 的 Current 已经迭代到最后一个元素了,才会执行 yield return 后面的语句。

协程的使用场景例子:

将一个复杂程序分帧执行;

制作计时器;

异步加载等功能,比如:

AB包资源的异步加载

Reaources资源的异步加载

场景的异步加载

WWW模块的异步请求

线程、进程、协程的区别:

进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。

线程拥有自己独立的栈和共享的堆,只共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。

协程和线程一样只共享堆,不共享栈,协程由程序员在协程的代码里显示调度。

一个应用程序一般对应一个进程,一个进程一般有一个主线程,还有若干个辅助线程,线程之间是并行的,在线程里面可以开启协程,协程是串行的,一个脚本中可以有多个协程,但同一时刻只有一个协程在运行。

协程和线程的区别是:协程避免了无意义的调度,由此可以提高性能,但也因此,程序员必须自己承担调度的责任,同时,协程也失去了标准线程使用多CPU的能力。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值