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. django启动时报错:Apps aren't loaded yet.

    1.解决方法 编辑manage.py文件,在文件顶部引入django模块.

  2. importlib 模块导入

    #1.动态导入模块 script_name = scripts.utils module = importlib.import_module(script_name) # 动态导入相应模块 #2.模块 ...

  3. SpringMVC请求流程

    Spring结构图 SpringMVC请求流程图 SpringMVC请求流程图语述: request--->DispatcherServler(中央调度器/前端控制器)---> Handl ...

  4. sql语句查看库里有没有这张表,有就删除

    查看库里有没有这张表,有就删除 DROP TABLE IF EXISTS 表名

  5. 如何解决Asp.Net MVC和WebAPI的Controller名称不能相同的问题

    1.问题描述 假如有一个文章的业务(Article),我们在 Controllers文件夹中创建MVC Controller和Api Controller,各个Controller中都有相同的获取文章 ...

  6. 阿里云 rails nginx 配置https访问

    1.申请免费型dv ssl证书:https://common-buy.aliyun.com/?spm=a2c4e.11155515.0.0.7zzvOZ&commodityCode=cas#/ ...

  7. chorme 插件

    json-handle: json可视化工具 开发中需要用到json,在浏览器显示的json非常乱,难以理解.有没有让人一目了然的工具,让json看起来非常直观呢,json-handle随之而出,包含 ...

  8. 搭建SSM项目时报错(org.springframework.jdbc.CannotGetJdbcConnectionException)

    严重: Servlet.service() for servlet [SpringMVC] in context with path [/ssm] threw exception [Request p ...

  9. [原创]java WEB学习笔记12:一个简单的serlet连接数据库实验

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  10. 对类型化数组(Typed Array)与ArrayBuffer的理解 转囧囧

    类型化数组(Typed Array)也是HTML5中新引入的API.用一句话解释类型化数组就是:它是JS操作二进制数据的接口. 众所周知,直接操作二进制数据可以使程序更为高效, 尽管JS对常规数组做了 ...