摘要下:

1.

coroutine, 中文翻译“协程”。这个概念可能有点冷门,不过百度之,说是一种很古老的编程模型了,以前的操作系统里进程调度里用到过,现在操作系统的进程调度都是根据 时间片和优先级来进行轮换,以前是要程序自己来释放cpu的控制权,一直不释放一直也就占用着cpu,这种要求程序自己来进行调度的编程模型应该就叫“协 程”了。

协程和线程差不多,线程的调度是由操作系统完成的,协程把这项任务交给了程序员自己实现,当然也就可以提高灵活性,另外协程的开销比线程要小,在程序里可以开更多的协程。

一些语言里自带了对coroutine的实现,比如lua。c里面虽然没有coroutine,不过windows下提供了一种叫fiber的机制,叫做“纤程”,算是一种轻量级线程。

2.

一。什么是协同程序

协同程序,即在主程序运行时同时开启另一段逻辑处理,来协同当前程序的执行。换句话说,开启协同程序就是开启一个线程。

二。协同程序的开启与终止

Unity3D中,使用MonoBehaviour.StartCoroutine方法即可开启一个协同程序,也就是说该方法必须在MonoBehaviour或继承于MonoBehaviour的类中调用。

在Unity3D中,使用StartCoroutine(string methodName)和StartCoroutine(IEnumerator routine)都可以开启一个线程。区别在于使用字符串作为参数可以开启线程并在线程结束前终止线程,相反使用IEnumerator  作为参数只能等待线程的结束而不能随时终止(除非使用StopAllCoroutines()方法);另外使用字符串作为参数时,开启线程时最多只能传递 一个参数,并且性能消耗会更大一点,而使用IEnumerator 作为参数则没有这个限制。

在Unity3D中,使用StopCoroutine(string methodName)来终止一个协同程序,使用StopAllCoroutines()来终止所有可以终止的协同程序,但这两个方法都只能终止该 MonoBehaviour中的协同程序。

还有一种方法可以终止协同程序,即将协同程序所在gameobject的active属性设置为false,当再次设置active为ture时,协同程 序并不会再开启;如是将协同程序所在脚本的enabled设置为false则不会生效。这是因为协同程序被开启后作为一个线程在运行,而  MonoBehaviour也是一个线程,他们成为互不干扰的模块,除非代码中用调用,他们共同作用于同一个对象,只有当对象不可见才能同时终止这两个线 程。然而,为了管理我们额外开启的线程,Unity3D将协同程序的调用放在了MonoBehaviour中,这样我们在编程时就可以方便的调用指定脚本 中的协同程序,而不是无法去管理,特别是对于只根据方法名来判断线程的方式在多人开发中很容易出错,这样的设计保证了对象、脚本的条理化管理,并防止了重 名。

我的一些粗浅小结:

1.Coroutines顾名思议是用来协助主要进程的,在Unity中感觉就是一个可动态添加和移除的Update()函数。它的调用在所有Update函数之后。

Unity原文:

  • If you start a coroutine in LateUpdate it will also be called after LateUpdate just before rendering.
  • Coroutines are executed after all Update functions.

2.yield就像是一个红绿灯,在满足紧跟在它后面的条件之前,这个协程会挂起,把执行权交给调用它的父函数,满足条件时就可以执行yield下面的代码。

Unity原文:

Normal coroutine updates are run after the Update function returns. A coroutine is function that can suspend its execution (yield) until the given given YieldInstruction finishes. Different uses of Coroutines:

  • yield;等待 all Update functions 已被call过,The coroutine will continue on the next frame.
  • yield WaitForSeconds(2);Continue after a specified time delay, after all Update functions have been called for the frame
  • yield WaitForFixedUpdate();Continue after all FixedUpdate has been called on all scripts
  • yield WWWContinue after a WWW download has completed.
  • yield StartCoroutine(MyFunc); Chains the coroutine, and will wait for the MyFunc coroutine to complete first.

协同的用法

Yield中断:(有中断就代表程序停在该处,等待yield后的时间结束再继续执行后面的语句。)

http://unity3d.com/support/documentation/ScriptReference/index.Coroutines_26_Yield.html

http://game.ceeger.com/Script/Overview/Overview.Coroutines_Yield.html

注意:

  • 在unity C#中yield(中断)语句必须要在IEnumerator类型里

  • C#方法,方法的返回类型为IEnumerator,返回值如(eg: yield return new WaitForSeconds(2);  或者 yield return null;)。

  • yields不可以在Update或者FixedUpdate里使用。

示例:
这个例子将执行Do,但是do之后的print会立刻执行:

 using UnityEngine;
using System.Collections; public class example : MonoBehaviour {
public static IEnumerator Do() {
  print("Do now");
  yield return new WaitForSeconds();
  print("Do 2 seconds later");
}
void Awake() {
  Do();    //执行DO,但是do后的语句继续执行
  print("This is printed immediately");
}

这个例子将执行Do,并等待,直到Do完成再执行其他语句:

 using UnityEngine;
using System.Collections; public class example : MonoBehaviour {
IEnumerator Do() {
print("Do now");
yield return new WaitForSeconds();
print("Do 2 seconds later");
}
IEnumerator Awake() {
yield return StartCoroutine("Do");    //Yield StartCoroutine就代表中断式的协同工作
print("Also after 2 seconds");
print("This is after the Do coroutine has finished execution");
}
}

Coroutine协同:(为什么要有Coroutine的概念? 因为有中断的存在,试想一个程序都靠Yield来暂停的话,如何做到一个事件暂停的过程中,暂停过程中继续执行后面的程序? 那么就要靠Coroutine来实现。)

http://unity3d.com/support/documentation/ScriptReference/MonoBehaviour.StartCoroutine.html?from=YieldInstruction

http://game.ceeger.com/Script/MonoBehaviour/MonoBehaviour.StartCoroutine.html

  • 可以在UPdate或者FixedUpdate里使用coroutine
  • 这里有两种:StartCoroutine(协同工作) 和 yield return StartCoroutine(中断式的协同工作)
  • 有yield的代表先执行完本语句(不管多长时间),或者执行完本yield方法调用,才执行后续语句。例如StartCoroutine(WaitAndPrint(2.0F)),继续执行StartCoroutine后面的语句,
  • 没有yield的代表继续顺序执行。例如:yield return StartCoroutine(WaitAndPrint(2.0F)),代表StartCoroutine(WaitAndPrint(2.0F))函数里等待全部执行完,再执行StartCoroutine后面的语句

StartCoroutine的例子:

 // In this example we show how to invoke a coroutine and continue executing
// the function in parallel.
// 此例演示如何调用协同程序和它的执行
function Start() {
// - After 0 seconds, prints "Starting 0.0"
// - After 0 seconds, prints "Before WaitAndPrint Finishes 0.0"
// - After 2 seconds, prints "WaitAndPrint 2.0"
// 先打印"Starting 0.0"和"Before WaitAndPrint Finishes 0.0"两句,2秒后打印"WaitAndPrint 2.0"
print ("Starting " + Time.time );
// Start function WaitAndPrint as a coroutine. And continue execution while it is running
// this is the same as WaintAndPrint(2.0) as the compiler does it for you automatically
// 协同程序WaitAndPrint在Start函数内执行,可以视同于它与Start函数同步执行.
StartCoroutine(WaitAndPrint(2.0));
print ("Before WaitAndPrint Finishes " + Time.time );
} function WaitAndPrint (waitTime : float) {
// suspend execution for waitTime seconds
// 暂停执行waitTime秒
yield WaitForSeconds (waitTime);
print ("WaitAndPrint "+ Time.time );
}

C# 版本

 using UnityEngine;
using System.Collections; public class example : MonoBehaviour {
void Start() {
print("Starting " + Time.time);
StartCoroutine(WaitAndPrint(2.0F));
print("Before WaitAndPrint Finishes " + Time.time);
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("WaitAndPrint " + Time.time);
}
}

yield return StartCoroutine的例子:

 // In this example we show how to invoke a coroutine and wait until it
// is completed
// 在这个例子中我们演示如何调用协同程序并直到它执行完成.
function Start() {
// - After 0 seconds, prints "Starting 0.0"
// - After 2 seconds, prints "WaitAndPrint 2.0"
// - After 2 seconds, prints "Done 2.0"
// 0秒时打印"Starting 0.0",2秒后打印"WaitAndPrint 2.0"和"Done 2.0"
print ("Starting " + Time.time );
// Start function WaitAndPrint as a coroutine. And wait until it is completed.
// the same as yield WaitAndPrint(2.0);
// 运行WaitAndPrint直到完成
yield StartCoroutine(WaitAndPrint(2.0));
print ("Done " + Time.time );
} function WaitAndPrint (waitTime : float) {
// suspend execution for waitTime seconds
// 等待waitTime秒
yield WaitForSeconds (waitTime);
print ("WaitAndPrint "+ Time.time );
}

C#版本

 using UnityEngine;
using System.Collections; public class example : MonoBehaviour {
IEnumerator Start() {
print("Starting " + Time.time);
yield return StartCoroutine(WaitAndPrint(2.0F));
print("Done " + Time.time);
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("WaitAndPrint " + Time.time);
}
}

Unity3D协同程序(Coroutine)的更多相关文章

  1. Lua 协同程序(coroutine)

    什么是协同(coroutine)? Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西. 协同是非常 ...

  2. (转)Unity3D协同程序(Coroutine)

    一.什么是协同程序 协同程序,即在主程序运行时同时开启另一段逻辑处理,来协同当前程序的执行.换句话说,开启协同程序就是开启一个线程. 二.协同程序的开启与终止 在Unity3D中,使用MonoBeha ...

  3. 【转】关于Unity协同程序(Coroutine)的全面解析

    http://www.unity.5helpyou.com/2658.html 本篇文章我们学习下unity3d中协程Coroutine的的原理及使用 1.什么是协调程序 unity协程是一个能暂停执 ...

  4. Lua中的协同程序 coroutine

    Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...

  5. Lua中的协同程序 coroutine(转)

    Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...

  6. Lua 学习之基础篇九<Lua 协同程序(Coroutine)>

    引言 讲到协程,首先来介绍一下线程和协程的区别 lua协程和多线程 相同之处:拥有自己独立的桟.局部变量和PC计数器,同时又与其他协程共享全局变量和其他大部分东西 不同之处:一个多线程程序可以同时运行 ...

  7. Lua学习笔记4. coroutine协同程序和文件I/O、错误处理

    Lua学习笔记4. coroutine协同程序和文件I/O.错误处理 coroutine Lua 的协同程序coroutine和线程比较类似,有独立的堆栈.局部变量.独立的指针指令,同时又能共享全局变 ...

  8. Lua 学习笔记(九)协同程序(线程thread)

    协同程序与线程thread差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的 ...

  9. Unity 中的协同程序

    今天咱就说说,协同程序coroutine.(这文章是在网吧敲的,没有unity,但是所有结论都被跑过,不管你信得过我还是信不过我,都要自己跑一下看看,同时欢迎纠错)先说说啥是协程:协同程序是一个非常让 ...

随机推荐

  1. MYSQL中 ENUM 类型

    MYSQL中 ENUM 类型的详细解释 ENUM类型 ENUM 是一个字符串对象,其值通常选自一个允许值列表中,该列表在表创建时的列规格说明中被明确地列举. 在下列某些情况下,值也可以是空串(&quo ...

  2. TextView支持的XML属性及相关方法

    1.android:auyoLink----->setAutoLinkMask(int) ----->是否将符合指定格式的文字转换为可单击的超链接形式 2.android:autoText ...

  3. FreeRTOS任务栈

    configTOTAL_HEAP_SIZE  定义堆大小,FreeRTOS 内核,用户动态内存申请,任务栈,任务创建,信号量创建,消息队列创建 等都需要用这个空间.

  4. 七牛php sdk 生成上传凭证时出现 undefined function Qiniu_SetKeys()

    将qiniu/http.php文件改名即可,原因是xampp等集成环境会安装pear存在了http.php

  5. 【原创】.NET之我见

    最近在准备面试,自己也顺带巩固了下基础,加上自己对码农的一些理解都写在这里了,水平不行,欢迎吐槽 //.NET基础 1.Class 和struct 区别 类是一种“引用类型”.创建类的对象时,对象赋值 ...

  6. TclError: no display name and no $DISPLAY environment variable

    %matplotlib inline 或 %matplotlib notebook

  7. 开始VS 2012 中LightSwitch系列的第2部分:感受关爱——定义数据关系

    [原文发表地址]  Beginning LightSwitch in VS 2012 Part 2: Feel the Love - Defining Data Relationships [原文发表 ...

  8. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.2,增加离线消息、离线文件功能(源码)

    (几句题外话:虽然就如何将GG发展为一个有商业价值的产品,我还没有很清晰明确的思路,但是从GG发布以来,通过GG认识了一些朋友,也接了一些小单子,赚了一点小钱.有了一点甜头,目前和2.3个好朋友一起做 ...

  9. 继续送假期干货——响应式图片工具smartImg

    中午看<众妙之门>看到一个响应式图片处理工具(点此查看)的介绍,然后就心血来潮想着不妨自己写一个基于JQ的吧,于是就又有了这么一个干货给大家. smartImg 的全部文件可以从我的Git ...

  10. 【腾讯Bugly干货分享】深入理解 ButterKnife,让你的程序学会写代码

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/578753c0c9da73584b025875 0.引子 话说我们做程序员的,都 ...