yield学习续:yield return迭代块在Unity3D中的应用——协程
2017-08-11 16:36
330 查看
必读好文推荐:
Unity协程(Coroutine)原理深入剖析
Unity协程(Coroutine)原理深入剖析再续
上面的文章说得太透彻,所以这里就记一下自己的学习笔记了。
首先要说明的是,协程并不是线程,协程是运行在主线程中的,是和主线程同步执行的代码,不同的地方是运行的方法可以被yield return在当前帧进行打断,到下一帧后可以继续从被打断的地方继续运行。
下面我们看一个示例,场景中有一个空的GameObject对象,其绑定了下面的脚本:
下面是执行的结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/21/1576eb57cbe28cbb45287ec167b9f351.png)
下面我们看看运行的逻辑是如何的:
当进入Start方法时开始启动协程,这时候协程开始运行,输出“step1”后遇到第一个yield return后暂停本帧的运行,接下来进入Update方法输出“frame1”,由于协程调用是在Update之后,所以第二帧开始后,先执行了第二个Update输出“frame2”,然后从协程的上次暂停处继续执行,输出“step2”后遇到第二个yield return后暂停本帧的运行,如此反复,当输出“step4”后发现方法已经执行完毕,协程结束。
下面看看yield break的效果,这个语句会立即中断协程的运行,代码如下:
下面是运行的结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/21/6acd2e53705e0d763ef25454a7000cf2.png)
我们可以发现“step4”已经运行不到了。
yield的返回值,我们可以返回null或者数字0,效果是一致的,同时还可以返回3个对象,分别如下:
·等待直到下一个固定帧速率更新函数。
·等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前。
·在给定的秒数内,暂停协同程序的执行。
下面我们来看一个例子,修改第一个例子的Test.cs:
运行的结果如下,有点长,我就弄成两张图了:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/21/6b4445acf7acc121f0721b01431ca898.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/21/4ae0c44244e6e66c1332b4ea0c60be72.png)
通过输出我们可以得出下面的结果:
当帧数波动时,FixedUpdate会进行多次补帧处理,我们可以发现两张图之间FixedUpdate从3一直补帧到15;
WaitForFixedUpdate表示协程是跟在FixedUpdate之后执行的;
WaitForEndOfFrame表示协程是跟在LateUpdate之后执行的;
WaitForSeconds额。。。不用多说了,你指定多久后执行就多久后执行,当然由于是基于帧运算的,所以可能会不准确;
最后补一张开头博客的运行顺序图:
Unity协程(Coroutine)原理深入剖析
Unity协程(Coroutine)原理深入剖析再续
上面的文章说得太透彻,所以这里就记一下自己的学习笔记了。
首先要说明的是,协程并不是线程,协程是运行在主线程中的,是和主线程同步执行的代码,不同的地方是运行的方法可以被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 }
下面是执行的结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/21/1576eb57cbe28cbb45287ec167b9f351.png)
下面我们看看运行的逻辑是如何的:
当进入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 }
下面是运行的结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/21/6acd2e53705e0d763ef25454a7000cf2.png)
我们可以发现“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 }
运行的结果如下,有点长,我就弄成两张图了:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/21/6b4445acf7acc121f0721b01431ca898.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/21/4ae0c44244e6e66c1332b4ea0c60be72.png)
通过输出我们可以得出下面的结果:
当帧数波动时,FixedUpdate会进行多次补帧处理,我们可以发现两张图之间FixedUpdate从3一直补帧到15;
WaitForFixedUpdate表示协程是跟在FixedUpdate之后执行的;
WaitForEndOfFrame表示协程是跟在LateUpdate之后执行的;
WaitForSeconds额。。。不用多说了,你指定多久后执行就多久后执行,当然由于是基于帧运算的,所以可能会不准确;
最后补一张开头博客的运行顺序图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/21/a95585f3f2c0e646ddeaebd5d0452ba0.png)
相关文章推荐
- yield学习续:yield return迭代块在Unity3D中的应用——协程
- yield学习续:yield return迭代块在Unity3D中的应用——协程
- unity3d 学习笔记___虚拟轴、鼠标事件、双击事件的应用处理
- Unity3D之协程(Coroutines & Yield )
- Unity3d之Vector3 学习与应用
- Unity3D之协程(Coroutines & Yield )
- Python 学习-yield 用法和协程
- Unity3d之Quaternion 学习与应用
- Unity3D之协程(Coroutines & Yield )
- Unity3d 5.x 学习笔记(4)—— Awake 与 Start 函数的区别于应用
- IEnumerator、yield及unity3d协程的手动驱动与合并
- Unity3d中协程的原理,你要的yield return new xxx的真正理解之道
- Unity3D 学习笔记6 ——协程
- Unity3D之协程(Coroutines & Yield )
- Unity3D之协程(Coroutines & Yield )
- Unity3D开发之协程(Coroutines & Yield)不执行的原因
- Unity3D之Mecanim动画系统学习笔记(十一):高级功能应用
- 【Unity3D游戏开发学习笔记】(四)一切都动起来—Animator组件的应用
- Unity3D之协程(Coroutines & Yield )
- 【python学习笔记】Python实现协程yield方法和gevent库