U3D协程yield的使用和理解

部分内容参考网址:http://blog.csdn.net/huang9012/article/details/29595747

Win7+U3D 4.6.7

1.在c#中使用
①首选需要定义一个返回值为IEnumerator的协程函数

1 IEnumerator Do(){
2     Debug.Log("Do 1");
3
4     yield return 0; //下面的代码延时到下一帧的update之后
5
6     Debug.Log("Do 2");
7 }

②使用StartCoroutine函数调用协程函数

1     void Start () {
2         Debug.Log("Start 1");
3         StartCoroutine(Do()); //调用协程函数
4         Debug.Log("Start 2");
5     }

③在Update函数中输出数字,判断Updata函数和协程之间的执行先后顺序

1 int i = 0;
2 void Update () {
3     ++i;
4     Debug.Log("Update " +i); //这里记录了调用update函数多少次
5 }

④在LateUpdate函数中输出数字,判断LateUpdate函数和协程之间的执行先后顺序

1 int j = 0;
2 void LateUpdate()
3 {
4     ++j;
5     Debug.Log("LateUpdate " + j); //这里记录了调用update函数多少次
6 }

⑤运行的输出顺序结果是:

 1 Start 1
 2 Do 1 //yield之后再下一帧的update之后继续执行
 3 Start 2
 4 Update 1//第一帧(当前帧)update执行完
 5 LateUpdate 1//第一帧(当前帧)的最后执行
 6 Update 2//第二帧(下一帧执行)update执行完
 7 Do 2//执行yield之后的代码
 8 LateUpdate 2//没错,LateUpdate在协程之后
 9 Update 3
10 LateUpdate 3
11 Update 4
12 LateUpdate 4
13 Update 5
14 LateUpdate 5…

2.关于协程的理解:
①在传统实时游戏中,在update中要延迟执行一些代码,或者满足一定条件后执行一些代码。需要在update添加一个计时器,用当前时间来减去前面记录的时间来判断执行。当这种情况越来越多的时候,会添加很多变量和代码,代码就越来越乱,这时候一般会抽象一个框架出来处理这个问题。协程就是解决这种问题的框架,换句话说yield return 0(return的是int值,任何值都一样,没有区别)的作用,就是在调用yield那行代码后(在yield函数处做一个记录标签),然后跳出协程函数继续执行外部的代码,在下一帧(是下一帧!)的update函数之后,根据yield函数的记录标签位置继续执行协程函数的后面部分代码。

yield return int是等待下一帧(应用场景:倒计时,分数累加,血条慢慢减少等)
yield return new new WaitForSeconds (2)是等待时间到
yield return new WWW(“http://chevin.net”)是等到页面响应
③协程和Update()一样更新,自然可以使用Time.deltaTime了,而且这个Time.deltaTime和在Update()当中使用是一样的效果(使用yield return int的情况下)
④协程并不是多线程,它和Update()一样是在主线程中执行的,所以不需要处理线程的同步与互斥问题
⑤yield return null其实没什么神奇的,只是unity3d封装以后,这个协程在下一帧就被自动调用了

3.为了更清楚的说明yield return int的下一帧执行的用处,分别使用两种方法实现同一个延时功能。
①使用update不断累加时间

 1 using UnityEngine;
 2 using System.Collections;
 3
 4   public class dialog_easy : MonoBehaviour {
 5       public string dialogStr = "一个一个字显示";
 6       public float speed = 5.0f;
 7
 8       private float timeSum = 0.0f;
 9      private bool isShowing = false;
10      // Use this for initialization
11      void Start () {
12          ShowDialog();
13      }
14
15      // Update is called once per frame
16      void Update () {
17          if(isShowing){
18              timeSum += speed * Time.deltaTime;
19              guiText.text = dialogStr.Substring(0, System.Convert.ToInt32(timeSum));
20
21              if(guiText.text.Length == dialogStr.Length)
22                  isShowing = false;
23          }
24      }
25
26      void ShowDialog(){
27          isShowing = true;
28          timeSum = 0.0f;
29      }
30 }

②使用yield return int每帧自动调用(明显这种用法简洁明了得多)

 1 using UnityEngine;
 2   using System.Collections;
 3
 4   public class dialog_yield : MonoBehaviour {
 5       public string dialogStr = "一个一个字显示";
 6       public float speed = 5.0f;
 7
 8       // Use this for initialization
 9       void Start () {
10          StartCoroutine(ShowDialog());
11      }
12
13      // Update is called once per frame
14      void Update () {
15      }
16
17      IEnumerator ShowDialog(){
18          float timeSum = 0.0f;
19          while(guiText.text.Length < dialogStr.Length){
20              timeSum += speed * Time.deltaTime;
21              guiText.text = dialogStr.Substring(0, System.Convert.ToInt32(timeSum));
22              yield return null;
23          }
24      }
25 }
时间: 2024-12-31 10:34:58

U3D协程yield的使用和理解的相关文章

生成器、协程(yield)

来自: https://en.wikipedia.org/wiki/Coroutine 生成器,也称为semicoroutines,[5]也是子程序的泛化,但比协同程序更受限制. 具体来说,虽然这两个都可以多次产生,暂停它们的执行并允许在多个入口点重新进入,但是它们的不同之处在于,协同程序可以控制在它们屈服之后执行继续的位置,而发生器不能,而是将控制转移回生成器的调用者 .[6] 也就是说,由于生成器主要用于简化迭代器的写入,所以生成器中的yield语句不指定要跳转到的协程,而是将值传递回父例程

(并发编程)进程池线程池--提交任务的2种方式、协程--yield greenlet,gevent模块

一:进程池与线程池(同步,异步+回调函数)先造个池子,然后放任务为什么要用"池":池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务池子内什么时候装进程:并发的任务属于计算密集型池子内什么时候装线程:并发的任务属于IO密集型 #提交任务的两种方式:    # 同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行的    # 异步调用:提交完一个任务之后,不在原地等待,结果???,而是

协程,yield,i多路复用,复习

课程回顾: 线程池 队列:同一进程内的队列 先进先出 后进先出 优先级队列 线程池中的回调函数是谁在调用? 线程池中的回调函数是子线程调用的,和父线程没有关系 进程池中的会点函数是父进程调用的,和子进程没有关系 今日内容: 为什么要有协程? 因为想要在单线程内实现并发的效果 因为CPthon有GIL锁,限制了在同一时间点,智能执行一个线程 所以想要在执行一个线程的期间,充分的利用cpu的性能 所以才有了想在单线程内实现并发的效果 并发: 切换+保存状态 1 因为某个程序阻塞了 2 因为某个程序用

谈谈对协程的理解

什么是协程 协程是在线程之上由“用户”构建的并发单元,对OS来说无感知,协程的切换由用户自己管理和调度.(这里的用户是相较于内核而言的,一些通用库这里也理解为用户) C/C++怎么实现协程 作为一个C++后台开发,我知道像go, lua之类的语言在语言层面上提供了协程的api,但是我比较关心C++下要怎么实现这一点,下面的讨论都是从C/C++程序员的角度来看协程的问题的. boost和腾讯都推出了相关的库,语言层面没有提供这个东西.我近期阅读了微信开源的libco协程库,协程核心要解决几个问题:

python协程:yield的使用

本文和大家分享的主要是python协程yield相关内容,一起来看看吧,希望对大家学习python有所帮助. 协程定义 协程的底层架构是在pep342 中定义,并在python2.5 实现的. python2.5 中,yield关键字可以在表达式中使用,而且生成器API中增加了 .send(value)方法.生成器可以使用.send(...)方法发送数据,发送的数据会成为生成器函数中yield表达式的值. 协程是指一个过程,这个过程与调用方协作,产出有调用方提供的值.因此,生成器可以作为协程使用

Python快速学习第十二天--生成器和协程

yield指令,可以暂停一个函数并返回中间结果.使用该指令的函数将保存执行环境,并且在必要时恢复. 生成器比迭代器更加强大也更加复杂,需要花点功夫好好理解贯通. 看下面一段代码: [python] view plain copy def gen(): for x in xrange(4): tmp = yield x if tmp == 'hello': print 'world' else: print str(tmp) 只要函数中包含yield关键字,该函数调用就是生成器对象. [pytho

FastRPC 3.2 发布,高性能 C++ 协程 RPC 框架

用过go erlang gevent的亲们应该都会知道协程在应用中带来的方便. 如果对协程不理解的同学,通过阅读下面例子可以快速了解我们框架的协程的意义,已了解的可以跳过这部分. 协程例子:假设我们要发个Get请求获取百度首页内容: php同步方式:$result = file_get_contents("http://www.baidu.com"), php果然是世界上最好的语言,多么简洁. 然后java和c++的同学开始不屑了: "呵呵, 同步,鄙视你不解释."

Python开发【第九篇】:协程、异步IO

协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是协程,协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切换回来的时候,恢复先前保存的寄存器上下文和栈.因此,协程能保留上一次调用的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法,进入上一次离开时所处逻辑流的位置. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返

进程,协程

一:进程:进程是操作系统结构的基础:是一个正在执行的程序:计算机中正在运行的程序实例:可以分配给处理器并由处理器执行的一个实体:由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元 1.多进程 由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程.Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情.借助这个包,可以轻松完成从