http://blog.csdn.net/nizihabi/article/details/47606887

一、Coroutine(协程)的概念和本质

在网上的一些资料当中,一直将Coroutine当作一个线程来描述,这样是不准确的。因为Coroutine并不是一个新的线程,它仍旧是属于主线程的一部分。Coroutine本质上是一种轻量级的thread,它的开销会比使用thread少很多。多个Coroutine可以按照次序在一个thread里面执行,一个Coroutine如果处于block状态,可以交出执行权,让其他的Coroutine继续执行。

而在Unity当中,Coroutine是在所有的Update函数执行完成之后才开始执行的,也就是在LateUpdate()之后执行,主要是用来协助主线程进行工作,就像手动添加了一个另外的update()函数在里面一样,一般情况下我们用于延时触发的功能。下面是关于MonoBehavior的执行顺序图,可以看到Coroutine是在LateUpdate之后的。

而我们注意到上图中,Coroutine左边标注着几个yield模块,这个就是我们下面要讲的如何使用Coroutine里的内容了。

二、Coroutine的使用

在Untiy里面,如果想要将一个函数Fun作为一个Coroutine使用,有两点是需要注意的
1、Fun的返回类型要为IEnumerator
2、yield的使用
 
yield ,在Coroutine里面更像是一个红绿灯的作用,在满足紧跟在它后面的条件之前,这个协程会挂起,把执行权交给调用它的父函数,满足条件时就可以执行yield下面的代码。大家可以执行一下下面的代码看看效果
  1. using UnityEngine;
  2. using System.Collections;
  3. public class ExampleClass : MonoBehaviour
  4. {
  5. IEnumerator WaitAndPrint()
  6. {
  7. // suspend execution for 5 seconds
  8. yield return new WaitForSeconds(5);
  9. print("WaitAndPrint " + Time.time);
  10. }
  11. IEnumerator Start()
  12. {
  13. print("Starting " + Time.time);
  14. // Start function WaitAndPrint as a coroutine
  15. yield return StartCoroutine("WaitAndPrint");
  16. print("Done " + Time.time);
  17. }
  18. }

大家应该能得到下面的输出(本人的Unity版本是5.0.1f1)

另外大家可以再执行一下下面的代码,可以观察一下看看跟上面的有何异同
  1. using UnityEngine;
  2. using System.Collections;
  3. public class ExampleClass : MonoBehaviour
  4. {
  5. IEnumerator WaitAndPrint()
  6. {
  7. // suspend execution for 5 seconds
  8. yield return new WaitForSeconds(5);
  9. print("WaitAndPrint " + Time.time);
  10. }
  11. void Start()
  12. {
  13. print("Starting " + Time.time);
  14. // Start function WaitAndPrint as a coroutine
  15. StartCoroutine("WaitAndPrint");
  16. print("Done " + Time.time);
  17. }
  18. }

得到的输出如下:

从上面可以看到,我们是通过StarCoroutine的方法来启动一个新的Coroutine的,在第一段代码当中,把Start方法也声明成一个IEnumerator类型的时候,当执行到yield 模块,就会进行阻塞,等待yield模块完成了之后再继续往下执行,而声名成普通类型的时候,当启动了新的Coroutine的时候,遇到yield了,并不会把整个Start阻塞,而是会记录下当前执行的位置,然后返回父函数中执行,每一帧过后会检测yield是否满足,当满足yield条件,则返回到yield后面执行。
 
在Unity3D中,使用StartCoroutine(string methodName)和StartCoroutine(IEnumerator routine)都可以开启一个线程。区别在于使用字符串作为参数可以开启线程并在线程结束前终止线程,相反使用IEnumerator 作为参数只能等待线程的结束而不能随时终止(除非使用StopAllCoroutines()方法);另外使用字符串作为参数时,开启线程时最多只能传递一个参数,并且性能消耗会更大一点,而使用IEnumerator 作为参数则没有这个限制。
 

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

还有一种终止Coroutine的方法,将gameObject的active属性设为False,但是设回true的时候并不会启动Coroutine。

注意:将Coroutine所在的脚本设为enable = false并不能够将Coroutine停止,因为它跟Monobehavior是同层级的。

Unity3D中的Coroutine及其使用(延时、定时调用函数)的更多相关文章

  1. Unity3D中的Coroutine详解

    Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...

  2. Unity3D中的Coroutine具体解释

    本文太乱,推荐frankjfwang的:全面解析Coroutine技术 Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这种代码. 疑问: yie ...

  3. 【Unity3D/C#】Unity3D中的Coroutine详解

    Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...

  4. Javascript中的定时调用函数setInterval()和setTimeout()

    首先介绍这两个函数 一.setInterval() 按照指定的周期来调用函数或表达式,执行多次.(时间单位:ms) timer = setInterval("content =documen ...

  5. JavaScript定时调用函数(SetInterval与setTimeout)

    setTimeout和setInterval的语法同样.它们都有两个參数.一个是将要运行的代码字符串.另一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将运行那段代码. 只是这两个函数还是有差别的 ...

  6. 怎样理解在函数中声明var x = y = 1后调用函数时, x是局部变量, y是全局变量

    下面这段代码在执行的时候, 打印的结果是1, Error: undefined; function fn() { var x = y = 1; } fn(); console.log(y); // 1 ...

  7. 【吐血推荐】简要分析unity3d中剪不断理还乱的yield

    在学习unity3d的时候很容易看到下面这个例子: void Start () { StartCoroutine(Destroy()); } IEnumerator Destroy(){ yield ...

  8. 【Unity3D】简要分析unity3d中剪不断理还乱的yield

    在学习unity3d的时候很容易看到下面这个例子: void Start () { StartCoroutine(Destroy()); } IEnumerator Destroy(){ yield ...

  9. 【转】简要分析unity3d中剪不断理还乱的yield

    在学习unity3d的时候很容易看到下面这个例子: 1 void Start () { 2 StartCoroutine(Destroy()); 3 } 4 5 IEnumerator Destroy ...

随机推荐

  1. fedora找开ftpd服务器并以root登陆

    工作原因需要在federal中弄个vsftpd再用root去登陆(我知道这样不太安全) 确认系统的版本 [root@localhost ~]# uname -a Linux localhost.loc ...

  2. SuperAgent使用文档

    SuperAgent是一个轻量级.灵活的.易读的.低学习曲线的客户端请求代理模块,使用在NodeJS环境中.官方文档:http://visionmedia.github.io/superagent 简 ...

  3. Delphi中Message消息的三种使用方法(覆盖WndProc,覆盖消息函数,改写WMCommand)

    实例1 unit Unit1; interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Fo ...

  4. 记一次bash脚本报错原因

    准备部署上次写的 爬虫的定时任务,发现sh脚本 写为最简单的cd ,也报错 后来网上一波了解,原因竟是 : 额,格式问题,我为了图方便是在window里用notepad++写的,然后我再linux 系 ...

  5. linux系统环境下搭建coreseek(+mmseg3) (good)

    1.下载并解压coreseek软件,操作命令如下: wget http://www.coreseek.cn/uploads/csft/3.2/coreseek-3.2.14.tar.gz 说明:文件下 ...

  6. linux shell 字符串操作(长度,查找,替换)

    感谢原创,文章很有帮助. 转自:http://www.cnblogs.com/chengmo/archive/2010/10/02/1841355.html 一.判断读取字符串值 表达式 含义 ${v ...

  7. NPM安装配置

    http://www.tuicool.com/articles/mmYZBn http://npm.taobao.org/ 安装Nodejs后即可开始NPM之旅了,新建一个package.json或者 ...

  8. 人生要golang

    第一篇 : 初识golang 第二篇 : 下载及安装 未完待续 ............................................

  9. Yii2 高级查询

    首先我们要自己写一个ActiveQuery 类并且继承 Yii2 的 ActiveQuery: namespace api\models; class ActiveQuery extends \yii ...

  10. HTML 5 本地存储

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...