yield学习续:yield return迭代块在Unity3D中的应用——协程
必读好文推荐:
上面的文章说得太透彻,所以这里就记一下自己的学习笔记了。
首先要说明的是,协程并不是线程,协程是运行在主线程中的,是和主线程同步执行的代码,不同的地方是运行的方法可以被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 }

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


通过输出我们可以得出下面的结果:
- 当帧数波动时,FixedUpdate会进行多次补帧处理,我们可以发现两张图之间FixedUpdate从3一直补帧到15;
- WaitForFixedUpdate表示协程是跟在FixedUpdate之后执行的;
- WaitForEndOfFrame表示协程是跟在LateUpdate之后执行的;
- WaitForSeconds额。。。不用多说了,你指定多久后执行就多久后执行,当然由于是基于帧运算的,所以可能会不准确;
最后补一张开头博客的运行顺序图:

yield学习续:yield return迭代块在Unity3D中的应用——协程的更多相关文章
- 学习PYTHON之路, DAY 10 进程、线程、协程篇
线程 线程是应用程序中工作的最小单元.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 直接调用 impo ...
- Python学习笔记整理总结【网络编程】【线程/进程/协程/IO多路模型/select/poll/epoll/selector】
一.socket(单链接) 1.socket:应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socke ...
- php yield关键字以及协程的实现
php的yield是在php5.5版本就出来了,而在初级php界却很少有人提起,我就说说个人对php yield的理解 Iterator接口 在php中,除了数组,对象可以被foreach遍历之外,还 ...
- 再议Python协程——从yield到asyncio
协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...
- (转)python协程2:yield from 从入门到精通
原文:http://blog.gusibi.com/post/python-coroutine-yield-from/ https://mp.weixin.qq.com/s?__biz=MzAwNjI ...
- python协程--yield和yield from
字典为动词“to yield”给出了两个释义:产出和让步.对于 Python 生成器中的 yield 来说,这两个含义都成立.yield item 这行代码会产出一个值,提供给 next(...) 的 ...
- Python异步IO之协程(一):从yield from到async的使用
引言:协程(coroutine)是Python中一直较为难理解的知识,但其在多任务协作中体现的效率又极为的突出.众所周知,Python中执行多任务还可以通过多进程或一个进程中的多线程来执行,但两者之中 ...
- 【Python】【容器 | 迭代对象 | 迭代器 | 生成器 | 生成器表达式 | 协程 | 期物 | 任务】
Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyn ...
- 流畅python学习笔记:第十六章:协程
通常在python进行编程一般都是使用多线程或者多进程来实现.这里介绍另外一种并发的方式,就是协程,但和多线程以及多进程不一样的是,协程是运行在单线程当中的并发.来看下具体的例子: def simpl ...
随机推荐
- Flash插件地址
Flash插件地址: http://get.adobe.com/cn/flashplayer/存档版本地址: http://helpx.adobe.com/flash-player/kb/archiv ...
- Archlinux添加MP3播放器
方法1: # pacman -S mplayer From: http://www.linuxdiyf.com/viewarticle.php?id=89207 用mplayer循环播放音乐:mpla ...
- 自动化测试selenium+java 环境搭建
1.开发环境: a:安装jdk,配置java的环境变量 b:安装eclipse 工具.火狐浏览器(低版本) 2.下载selenium包 selenium-java-2.44.0.jar seleniu ...
- VM 虚拟机 Error 1324. The path My Documents contains a invalid chara 。
当安装VM(虚拟机)时,安装到一半时,提示:Error 1324. The path My Documents contains a invalid chara . 就是提示路径无效. 按下面的路径: ...
- Java内各种进制的表示
不同进制的数据表现: 二进制:由0,1组成.以0b开头. 八进制:由0,1,...7组成.以0开头. 十进制:由0,1,...9组成.默认整数是十进制. 十六进制:由0,1,...9,a,b,c,d, ...
- ubuntu 开机显示错误:无法应用原保存的显示器配置
无法应用原保存的显示器配置CRTC 63:尝试 800x600@60Hz 模式输出在 1366x768@60Hz (通过 0)CRTC 63:尝试 2560x1600@60Hz 模式输出在 1366x ...
- 实现textarea限制输入字数(包含中文只能输入10个,全ASCII码能够输入20个)
document.getElementById("<%=textBox1.ClientID %>").value 实现textarea限制输入字数(包含中文只能输入10 ...
- 修改Tomcat根目录
在server.xml文件中找到</Host>标签,在之前加入这样一行:<Context path="" docBase="F:/MyWeb" ...
- 案例:TableLayout表格布局——迷你计算器
计算器可以常用线性布局(LinearLayout)和表格布局(tableLayout).Gridlayout 今天我用的是表格布局 效果如下: 代码如下: <TableLayout xmlns: ...
- JAVA定义接口格式:
[public]interface 接口名称 [extends父接口名列表] { //静态常量 [public] [static] [final] 数据类型变量名=常量值; //抽象方法 [publi ...