Unity 协程(Coroutine)原理与用法详解 (2)

在了解这些yield的方法后,可以通过下面的代码来理解其执行顺序:

void Update() { Debug.Log("001"); StartCoroutine("Demo"); Debug.Log("003"); } private void LateUpdate() { Debug.Log("005"); } IEnumerator Demo() { Debug.Log("002"); yield return 0; Debug.Log("004"); }

将上面的脚本挂载到物体上,运行游戏场景,来查看打印的日志,可以看到下面的日志记录:

在这里插入图片描述


可以很清晰的看出,协程虽然是在Update中开启,但是关于yield return null后面的代码会在下一帧运行,并且是在Update执行完之后才开始执行,但是会在LateUpdate之前执行

接下来看几个特殊的yield,他们是用在一些特殊的区域,一般不会有机会去使用,但是对于某些特殊情况的应对会很方便

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

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

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

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

通过上面的一些yield一些用法以及其在脚本生命周期中的位置,我们也可以看到关于协程不是线程的概念的具体的解释,所有的这些方法都是在主线程中进行的,只是有别于我们正常使用的Update与LateUpdate这些可视的方法

5、线程几个小用法

5.1、将一个复杂程序分帧执行:

如果一个复杂的函数对于一帧的性能需求很大,我们就可以通过yield return null将步骤拆除,从而将性能压力分摊开来,最终获取一个流畅的过程,这就是一个简单的应用

举一个案例,如果某一时刻需要使用Update读取一个列表,这样一般需要一个循环去遍历列表,这样每帧的代码执行量就比较大,就可以将这样的执行放置到协程中来处理:

public class Test : MonoBehaviour { public List<int> nums = new List<int> { 1, 2, 3, 4, 5, 6 }; private void Update() { if(Input.GetKeyDown(KeyCode.Space)) { StartCoroutine(PrintNum(nums)); } } //通过协程分帧处理 IEnumerator PrintNum(List<int> nums) { foreach(int i in nums) { Debug.Log(i); yield return null; } } }

上面只是列举了一个小小的案例,在实际工作中会有一些很消耗性能的操作的时候,就可以通过这样的方式来进行性能消耗的分消

5.2、进行计时器工作

当然这种应用场景很少,如果我们需要计时器有很多其他更好用的方式,但是你可以了解是存在这样的操作的,要实现这样的效果,需要通过yield return new WaitForSeconds()的延时执行的功能:

IEnumerator Test() { Debug.Log("开始"); yield return new WaitForSeconds(3); Debug.Log("输出开始后三秒后执行我"); }

5.3、异步加载等功能

只要一说到异步,就必定离不开协程,因为在异步加载过程中可能会影响到其他任务的进程,这个时候就需要通过协程将这些可能被影响的任务剥离出来

常见的异步操作有:

AB包资源的异步加载

Reaources资源的异步加载

场景的异步加载

WWW模块的异步请求

这些异步操作的实现都需要协程的支持,可以通过我之前的一篇场景加载界面实现的文章来理解该内容:

关于异步的文章:

Unity 场景异步加载(加载界面的实现)

总结

通过上面的一些操作,相信你应该理解协程的基本原理与用法,以及一些相关的小知识

因为协程本身也是一个比较复杂的概念,所以我的理解也可能有错误的地方,如果你发现文章中有哪些不正确的地方,欢迎留言指出< ^ _ ^ >

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjszy.html