我是快乐的搬运工 http://blog.csdn.net/u011397120/article/details/61236055

---------------------------------------------------------------------- 分割线 xx --------------------------------------------------------------------------

本文是个人对Unity协程的一些理解和总结.Unity协程长的有点像线程,但却不是线程.因为协程仍然是在主线程中执行,且在使用时不用考虑同步与锁的问题.协程只是控制代码等到特定的时机后再执行后续步骤.

启动协程

Unity 5.x中使用StartCoroutine方法开启协程,其方式有以下几种.

  1. //形式一
  2. StartCoroutine(CustomCorutineFn());
  3. StartCoroutine(CustomCorutineFn(7));//向方法中传递参数
  4. //形式二
  5. StartCoroutine(“CustomCorutineFn”);
  6. StartCoroutine(“CustomCorutineFn”,7);//向方法中传递参数

以上两种形式都可开起当前MonoBehaviour对象的协程,注意:当你想停止MonoBehaviour对象中的某个协程时,开启与停止协程需要使用相同的形式,不可混合使用.
协程中有多种等待方式,例如:等到FixedUpdate结束后才执行,代码如下.

  1. bool canExcute = true;
  2. void FixedUpdate()
  3. {
  4. if (canExcute)
  5. {
  6. Debug.Log("FixedUpdate" );
  7. }
  8. }
  9. IEnumerator Corutine_WaitForFixedUpdate()
  10. {
  11. yield return new WaitForFixedUpdate();
  12. Debug.Log(string .Format("====>{0} time:{1}", 1, Time .time));
  13. yield return new WaitForFixedUpdate();
  14. Debug.Log(string .Format("====>{0} time:{1}", 2, Time .time));
  15. }

输出结果如下.

官方文档Monobehaviour的函数执行顺序图,就对协程再次执行的时机做了很好的描述.

以上只是一个示意图,详细信息请看官方文档.
链接 https://docs.unity3d.com/Manual/ExecutionOrder.html

  1. yield null:协程将在下一帧所有脚本的Update执行之后,再继续执行.
  2. yield WaitForSeconds:协程在延迟指定时间,且当前帧所有脚本的 Update全都执行结束后才继续执行.
  3. yield WaitForFixedUpdate:协程在所有脚本的FixedUpdate执行之后,再继续执行.
  4. yield WWW:协程在WWW下载资源完成后,再继续执行.
  5. yield StartCoroutine:协程在指定协程执行结束后,再继续执行.
  6. WaitForSecondsRealtime:与WaitForSeconds类似,但不受时间缩放影响.
  7. WaitWhile:当返回条件为假时才执行后续步骤.

协程的执行也会受到其他因素的影响,例如:当时间缩放值Time.timeScale被修改后,放大或者缩小.FixedUpdate 方法会受影响,则WaitForFixedUpdate也会跟着受影响;当Update方法中同步加载较大的对象时,WaitForSeconds所指定的时间就可能会与实际的时间不一致.所以在执行协程等待时,要视情况而定.

多个gameObject对象开启协程,执行顺序又是如何呢?
假如场景中存在A,B两个gameObject对象,均使用WaitForFixedUpdate方式等待,则等待执行的部分,会在A,B两个对象的FixedUpdate都执行结束后,才开始执行当前帧后续可执行的部分.源码如下:

  1. void Awake()
  2. {
  3. StartCoroutine(Corutine_WaitForFixedUpdate());
  4. }
  5. IEnumerator Corutine_WaitForFixedUpdate()
  6. {
  7. Debug.Log(string .Format("A : {0}", 0));
  8. yield return new WaitForFixedUpdate();
  9. Debug.Log(string .Format("A : {0}", 1));
  10. }
  11. bool canExcute = false;
  12. void FixedUpdate()
  13. {
  14. if (!canExcute)
  15. {
  16. canExcute = true;
  17. Debug.Log("A FixedUpdate" );
  18. }
  19. }

执行后,输出结果如下.

停止协程

在开发中可能会开启多个协程,如果你想停止其中某个协程,你可使用StopCoroutine.但在使用时,你需要注意一点,停止协程的方式要与开启协程的方式一致.StopCoroutine(“CustomCorutineFn”)必须与StartCoroutine(“CustomCorutineFn”)成对使用,与StartCoroutine(CustomCorutineFn())一起使用则完全无效.
通过StopCoroutine的重载方法可知道,还有两种方式可停止协程.在此举个例子,如下:

  1. IEnumerator cor;
  2. void Awake()
  3. {
  4. //注意保存IEnumerator变量.
  5. cor = Corutine_WaitForFixedUpdate();
  6. StartCoroutine(cor);
  7. StartCoroutine(Corutine_Stop());
  8. }
  9. IEnumerator Corutine_WaitForFixedUpdate()
  10. {
  11. Debug.Log(string .Format("A : {0}", 0));
  12. yield return new WaitForEndOfFrame();
  13. Debug.Log(string .Format("A : {0}", 1));
  14. }
  15. IEnumerator Corutine_Stop()
  16. {
  17. yield return new WaitForFixedUpdate();
  18. //通过cor停止协程
  19. //而不是this.StopCoroutine(Corutine_WaitForFixedUpdate());
  20. this.StopCoroutine(cor);
  21. }

如果想停止多个协程,可使用StopAllCoroutines方法,但这种方法只能停止当前MonoBehaviour类实例中所有协程.其他不受影响.
如果想停止gameObject上所有脚本组件中的协程,禁用脚本组件是无法停止协程的,只需要禁用gameObject即可.

如何用协程的输出10组计数(每组5次,每次1秒)?
源码如下:

  1. using System.Collections;
  2. using UnityEngine;
  3.  
  4. public class mCorutine : MonoBehaviour
  5. {
  6. public float time = 1;
  7. void Awake()
  8. {
  9. StartCoroutine(FirstLayerCorutine());
  10. }
  11. IEnumerator FirstLayerCorutine()
  12. {
  13. for (int i = 0; i < 10; i++)
  14. {
  15. Debug.Log(string .Format("第{0}组", i + 1));
  16. yield return StartCoroutine(SecondLayerCorutine());
  17. }
  18. }
  19. IEnumerator SecondLayerCorutine()
  20. {
  21. for (int i = 0; i < 5; i++)
  22. {
  23. Debug.Log(string .Format("{0}", i + 1));
  24. yield return new WaitForSeconds(time);
  25. }
  26. }
  27. }

协程的使用还有很多要注意的地方,在这里分享一个关于协程运行时的监控和优化的链接.
http://gulu-dev.com/post/perf_assist/2016-12-20-unity-coroutine-optimizing

Unity3D 协程的介绍和使用的更多相关文章

  1. Unity3D协程yield的理解

    Unity3D的协程概括地将就是:对于一段程序,你可以加上yield标明哪里需要暂停,然后在下一帧或者一段时间后,系统会继续执行这段代码.协程的作用:①延迟一段时间执行代码.②等某个操作完成之后再执行 ...

  2. [转]Unity3D协程介绍 以及 使用

    作者ChevyRay ,2013年9月28日,snaker7译  原文地址:http://unitypatterns.com/introduction-to-coroutines/ 在Unity中,协 ...

  3. Unity3D协程介绍 以及 使用

    作者ChevyRay ,2013年9月28日,snaker7译  原文地址:http://unitypatterns.com/introduction-to-coroutines/ 在Unity中,协 ...

  4. Unity3d 协程的注意问题(新手须注意,老手须加勉)

    关于unity3d的协程,非常的好用,比如等待几秒执行,等待下一帧执行等! 但是也有潜在的问题: 1.协程是单线程的,在主线程中完成 2.如果发现yield, 那么这一帧会结束,那么等下一帧调用此脚本 ...

  5. Unity3D 协程 浅谈

    协程 理解:协程不是线程,也不是异步执行(知道就行). 1.协程和MonoBehaviour的Update函数一样,也是在MainThread中执行的(一定得明白这句话意思). void Start ...

  6. Unity3d 协程

    参考文章: http://blog.csdn.net/onafioo/article/details/48979939 http://www.cnblogs.com/zhaoqingqing/p/37 ...

  7. Unity3D协程

    协程介绍 Unity的协程系统是基于C#的一个简单而强大的接口 ,IEnumerator,它允许你为自己的集合类型编写枚举器.这一点你不必关注太多,我们直接进入一个简单的例子来看看协程到底能干什么.首 ...

  8. Unity3D协程(转)

    这篇文章转自:http://blog.csdn.net/huang9012/article/details/38492937 协程介绍 在Unity中,协程(Coroutines)的形式是我最喜欢的功 ...

  9. Unity3D 协程 Coroutine

    协程(Coroutine)的概念存在于很多编程语言,例如Lua.ruby等.而由于Unity3D是单线程的,因此它同样实现了协程机制来实现一些类似于多线程的功能,但是要明确一点协程不是进程或线程,其执 ...

随机推荐

  1. 2018--Linux命令总结整理复习版

    一.ls命令: 用来显示目标列表,在Linux中是使用率较高的命令.ls命令的输出信息可以进行彩色加亮显示,以分区不同类型的文件. -a:显示所有档案及目录(ls内定将档案名或目录名称为“.”的视为影 ...

  2. call 和 apply 用法

    ECMAScript规范中,所有函数都包含这两个方法,并且两个方法的使用基本一致,都是用于改变函数的作用域,即改变函数体内 this 指向.不同的是 call 方法的第二个参数可以接收任意个参数,以逗 ...

  3. Deep Image Retrieval: Learning global representations for image search In ECCV, 2016学习笔记

    - 论文地址:https://arxiv.org/abs/1604.01325 contribution is twofold: (i) we leverage a ranking framework ...

  4. linux(centos6.9)下rpm方式安装mysql后mysql服务无法启动

    以下两种方式启动都报错:启动失败: [root@node03 ~]# service mysqld startMySQL Daemon failed to start.Starting mysqld: ...

  5. springmvc 后台实体类接受前端json字符串时,其中一个属性content 接受富文本内容时 标签<p>、<span> 这些标签丢失问题解决

    问题描述: 前端一个字段 <script id="editor" type="text/plain" name="content" s ...

  6. 冰蝎动态二进制加密WebShell特征分析

    概述 冰蝎一款新型加密网站管理客户端,在实际的渗透测试过程中有非常不错的效果,能绕过目前市场上的大部分WAF.探针设备.本文将通过在虚拟环境中使用冰蝎,通过wireshark抓取冰蝎通信流量,结合平时 ...

  7. SpringAOP源码跟踪及学习

    Spring 版本 4.3.2 在拿到 Bean 实例以后,会经历一系列的初始化工作,如:工厂回调.init 方法.后处理器在 Bean 初始化前后的处理等,在一般情况下(非 factory-meth ...

  8. 初学Java(1)

    1.Java基本数据类型: 2.Java的main方法: 被static修饰,类名与文件名相同:void:方法的返回值,无返回值:main方法是程序的入口,有且只有一个: String[] args: ...

  9. Docker自建本地仓库

    1.安装docker yum install docker -y 之后根据需求把指定docker安装目录,或者新建一个磁盘使用docker-storage-setup来使用 2.设置第三方docker ...

  10. ROM与RAM

    今天小姐姐来问我关于ROM.RAM和Flash的区别,我给她大致的说了一下名称和作用.可人家说她知道这玩意的名字,希望我能够接地气的解释一下什么是ROM.RAM.FLASH…… 这就把我难住了 ≧ ﹏ ...