博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
yield学习续:yield return迭代块在Unity3D中的应用——协程
阅读量:6500 次
发布时间:2019-06-24

本文共 4149 字,大约阅读时间需要 13 分钟。

必读好文推荐:

 

上面的文章说得太透彻,所以这里就记一下自己的学习笔记了。

首先要说明的是,协程并不是线程,协程是运行在主线程中的,是和主线程同步执行的代码,不同的地方是运行的方法可以被yield return在当前帧进行打断,到下一帧后可以继续从被打断的地方继续运行。

下面我们看一个示例,场景中有一个空的GameObject对象,其绑定了下面的脚本:

1 using UnityEngine; 2 using System.Collections; 3  4 public class Test : MonoBehaviour 5 { 6     int frame = 0; 7  8     void Start () 9     {10         this.StartCoroutine(CountDown());11     }12     13     void Update ()14     {15         Debug.Log("Now is frame: " + (++frame));16     }17 18     IEnumerator CountDown()19     {20         Debug.Log("step - 1");21         yield return null;22         Debug.Log("step - 2");23         yield return null;24         Debug.Log("step - 3");25         yield return null;26         Debug.Log("step - 4");27     }28 }

下面是执行的结果:

下面我们看看运行的逻辑是如何的:

当进入Start方法时开始启动协程,这时候协程开始运行,输出“step1”后遇到第一个yield return后暂停本帧的运行,接下来进入Update方法输出“frame1”,由于协程调用是在Update之后,所以第二帧开始后,先执行了第二个Update输出“frame2”,然后从协程的上次暂停处继续执行,输出“step2”后遇到第二个yield return后暂停本帧的运行,如此反复,当输出“step4”后发现方法已经执行完毕,协程结束。

 

下面看看yield break的效果,这个语句会立即中断协程的运行,代码如下:

1 using UnityEngine; 2 using System.Collections; 3  4 public class Test : MonoBehaviour 5 { 6     int frame = 0; 7  8     void Start () 9     {10         this.StartCoroutine(CountDown());11     }12     13     void Update ()14     {15         Debug.Log("Now is frame: " + (++frame));16     }17 18     IEnumerator CountDown()19     {20         Debug.Log("step - 1");21         yield return null;22         Debug.Log("step - 2");23         yield return null;24         Debug.Log("step - 3");25         yield break;26         Debug.Log("step - 4");27     }28 }

下面是运行的结果:

我们可以发现“step4”已经运行不到了。

 

yield的返回值,我们可以返回null或者数字0,效果是一致的,同时还可以返回3个对象,分别如下:

yield return new WaitForFixedUpdate();

·等待直到下一个固定帧速率更新函数。

yield return new WaitForEndOfFrame();

·等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前。

yield return new WaitForSeconds(1);

·在给定的秒数内,暂停协同程序的执行。

 

下面我们来看一个例子,修改第一个例子的Test.cs:

1 using UnityEngine; 2 using System.Collections; 3  4 public class Test : MonoBehaviour 5 { 6     int frame1 = 0; 7     int frame2 = 0; 8     int frame3 = 0; 9 10     void Start ()11     {12         this.StartCoroutine(CountDown());13         this.StartCoroutine(CountDown_WaitForFixedUpdate());14         this.StartCoroutine(CountDown_WaitForEndOfFrame());15         this.StartCoroutine(CountDown_WaitForSeconds());16     }17     18     void Update ()19     {20         Debug.Log("Update is frame: " + (++frame1));21     }22 23     void FixedUpdate ()24     {25         Debug.Log("FixedUpdate is frame: " + (++frame2));26     }27 28     void LateUpdate ()29     {30         Debug.Log("LateUpdate is frame: " + (++frame3));31     }32 33     IEnumerator CountDown()34     {35         Debug.Log("yield - step - 1");36         yield return null;37         Debug.Log("yield - step - 2");38         yield return null;39         Debug.Log("yield - step - 3");40     }41 42     IEnumerator CountDown_WaitForFixedUpdate()43     {44         Debug.Log("yield WaitForFixedUpdate - step - 1");45         yield return new WaitForFixedUpdate();46         Debug.Log("yield WaitForFixedUpdate - step - 2");47         yield return new WaitForFixedUpdate();48         Debug.Log("yield WaitForFixedUpdate - step - 3");49     }50 51     IEnumerator CountDown_WaitForEndOfFrame()52     {53         Debug.Log("yield WaitForEndOfFrame - step - 1");54         yield return new WaitForEndOfFrame();55         Debug.Log("yield WaitForEndOfFrame - step - 2");56         yield return new WaitForEndOfFrame();57         Debug.Log("yield WaitForEndOfFrame - step - 3");58     }59 60     IEnumerator CountDown_WaitForSeconds()61     {62         Debug.Log("yield WaitForSeconds - step - 1");63         yield return new WaitForSeconds(1 / 60 * 3);//大概是三帧的时间64         Debug.Log("yield WaitForSeconds - step - 2");65         yield return new WaitForSeconds(1 / 60 * 3);66         Debug.Log("yield WaitForSeconds - step - 3");67     }68 }

运行的结果如下,有点长,我就弄成两张图了:

 

通过输出我们可以得出下面的结果:

  1. 当帧数波动时,FixedUpdate会进行多次补帧处理,我们可以发现两张图之间FixedUpdate从3一直补帧到15;
  2. WaitForFixedUpdate表示协程是跟在FixedUpdate之后执行的;
  3. WaitForEndOfFrame表示协程是跟在LateUpdate之后执行的;
  4. WaitForSeconds额。。。不用多说了,你指定多久后执行就多久后执行,当然由于是基于帧运算的,所以可能会不准确;

 

最后补一张开头博客的运行顺序图:

转载地址:http://sbvyo.baihongyu.com/

你可能感兴趣的文章
TensorFlow的基本运算01
查看>>
怎么看电脑有没有安装USB3.0驱动
查看>>
overflow清除浮动的原理
查看>>
Spring Boot 使用parent方式引用时 获取值属性方式默认@
查看>>
解决maven下载jar慢的问题(如何更换Maven下载源)
查看>>
linux安装gitLab
查看>>
concurrent包的实现示意图
查看>>
golang os.Args
查看>>
Linux常用命令
查看>>
spring-data-elasticsearch 概述及入门(二)
查看>>
Solr启动和结束命令
查看>>
1.12 xshell密钥认证
查看>>
3.2 用户组管理
查看>>
VMware虚拟机出现“需要整合虚拟机磁盘”的解决方法
查看>>
ibatis 动态查询
查看>>
汇编语言之实验一
查看>>
git 调用 Beyond Compare
查看>>
SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)[转]
查看>>
android实现图片识别的几种方法
查看>>
mvc学习地址
查看>>