0x00 前言

在使用Unity的过程中,对协程仅仅知道怎样使用,但并不知道协程的内部机理,对于自己不清楚的部分就像一块大石压力心里。让自己感觉到担忧和不适。

这篇文章一探到底,彻底揭开协程的面纱,让大家在使用中不再有后顾之忧。

0x01 概念

协程是:程序组件来生成非抢占式多任务子函数,生成的子函数同意在程序里挂起和唤醒操作。

0x02 使用场景

通常协程能够非常方便实现延时操作。以及异步载入操作。以下是两个简单协程使用样例。

延时操作

// Use this for initialization
void Start () {
StartCoroutine (Wait ());
} IEnumerator Wait(){
Debug.Log ("start time:" + Time.time);
yield return new WaitForSeconds (1);
Debug.Log ("time:" + Time.time);
yield return new WaitForSeconds(2);
Debug.Log ("time:" + Time.time);
}

异步载入资源

// Use this for initialization
void Start () {;
System.Action<string> callBack = delegate(string text) {
Debug.Log(text);
};
StartCoroutine (LoadRes (callBack));
} IEnumerator LoadRes(System.Action<string> callBack){
WWW www = new WWW ("http://www.baidu.com");
yield return www; if (string.IsNullOrEmpty (www.error)) {
callBack(www.text);
Debug.Log("load success");
}
else{
Debug.Log("load failed");
}
}

0x03 原理

Unity里的协程通过定义一个返回 IEnumerator类型的函数。先来通过一个函数看看Unity都能返回那些类型:

IEnumerator Test(){
yield return 2; // 返回整数
yield return 4.2; // 返回浮点数
yield return null; // 返回null
yield return new WaitForSeconds(1); // 返回instance
yield return new WWW ("http://www.baidu.com"); // 返回instance
}

返回的类型有什么要求?整理一下Unity都实现了那些返回类型:

1、int类型,须要等待的帧数

2、float类型,须要等待的时间(秒)

3、null,等待一帧

4、break,结束协程

5、实例,必须有bool isDone()成员函数,等isDone返回true

6、IEnumerator,等IEnumerator实例的MoveNext()返回false

Unity的返回类型知道了,怎样捕获这些返回类型?来看IEnumerator怎样实现的?

public interface IEnumerator
{
//
// Properties
//
object Current
{
get;
} //
// Methods
//
bool MoveNext (); void Reset ();
}

通过研究IEnumerator接口,得到通过调用MoveNext。我们能够得到遍历全部yield返回的值,返回的值能够通过Current得到。每次调用MoveNext都会运行夹在yield中间的代码。

写个測试程序来验证我们的理论:

public class game_client : MonoBehaviour {

    // Use this for initialization
void Start () {
IEnumerator i = Test ();
while (true) {
if(!i.MoveNext()){
break;
}
object cur = i.Current;
if(cur != null)
Debug.Log(cur.GetType());
else
Debug.Log("type is null");
}
} IEnumerator Test(){
yield return 2;
yield return 4.2;
yield return null;
yield return new WaitForSeconds(1);
yield return new WWW ("http://www.baidu.com");
}
}

通过验证程序。能够得到yield返回的值。有了这些值,就能够实现自己的协程。

0x04 实现

设计接口:

class ScheduleCoroutine
{
public void StartCoroutine(IEnumerator coroutine);
public void StopCoroutine(IEnumerator coroutine);
public void Update(int frame, float time);
}

设计数据结构:

class CoroutineNode{
public IEnumerator itor;
public string name;
public int frame;
public float time;
public Object instance;
public CoroutineNode pre;
public CoroutineNode next;
}

详细实现代码,对于不同的项目需求,有不同的实现方式。这篇文章主要是探寻Unity协程的实现方式。

搞清楚原理后,在使用上就会更加得心应手。

0x05 參考

文章參考了非常多其它博文。感谢他们的付出。

在第一个參考链接里。有详细实现代码。

1、

title=CoroutineScheduler">UnifyWiki

2、维基百科

Unity 协程使用指南的更多相关文章

  1. Unity协程(Coroutine)管理类——TaskManager工具分享

    博客分类: Unity3D插件学习,工具分享 源码分析   Unity协程(Coroutine)管理类——TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处 ...

  2. Unity协程(Coroutine)原理深入剖析

    Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 其实协程并没有那么复杂,网上很多地方都说是多 ...

  3. Unity协程(Coroutine)原理深入剖析(转载)

    记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield r ...

  4. unity协程coroutine浅析

    转载请标明出处:http://www.cnblogs.com/zblade/ 一.序言 在unity的游戏开发中,对于异步操作,有一个避免不了的操作: 协程,以前一直理解的懵懵懂懂,最近认真充电了一下 ...

  5. Unity协程Coroutine使用总结和一些坑

    原文摘自 Unity协程Coroutine使用总结和一些坑 MonoBehavior关于协程提供了下面几个接口: 可以使用函数或者函数名字符串来启动一个协程,同时可以用函数,函数名字符串,和Corou ...

  6. 深入浅出!从语义角度分析隐藏在Unity协程背后的原理

    Unity的协程使用起来比较方便,但是由于其封装和隐藏了太多细节,使其看起来比较神秘.比如协程是否是真正的异步执行?协程与线程到底是什么关系?本文将从语义角度来分析隐藏在协程背后的原理,并使用C++来 ...

  7. Unity协程(Coroutine)原理深入剖析再续

    Unity协程(Coroutine)原理深入剖析再续 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 前面已经介绍过对协程(Coroutine ...

  8. Unity协程使用经验

    [Unity协程使用经验] 1.协程的好处是,异步操作发起的地方和结束的地方可以统一在一个方法,这样就不用引入额外的成员变量来进行状态同步. 2.在一个协程中,StartCoroutine()和 yi ...

  9. 【转】Unity协程(Coroutine)原理深入剖析

    Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 记得去年6月份刚开始实习的时候,当时要我写网 ...

随机推荐

  1. sublime双击选择全选带中划线

    // Characters that are considered to separate words "word_separators": "./\\()\" ...

  2. 【进阶修炼】——改善C#程序质量(6)

    90,不应为抽象类指定public的构造函数. 抽象类即使指定了public的构造函数,也是不能实例化的,编译通不过.抽象类的构造函数应该设定为protected,它的作用应该是初始化自己的成员,以及 ...

  3. docker监控

    [编者的话]这篇文章作者是Usman,他是服务器和基础架构工程师,有非常丰富的分布式构建经验.该篇文章主要分析评估了五种Docker监控工具,包括免费的和不免费的:Docker Stats.CAdvi ...

  4. SpringBoot2 集成三种连接池 c3p0 hikari druid

    Hikari 1.首先集成 hikari springboot默认集成,只需要简单的配置即可 1.1 首先导入包 <dependency> <groupId>com.zaxxe ...

  5. mongoimport 导入数据

    最后 利用mongodb自带的mongoimport工具可以上传csv文件 命令如下 mongoimport -h localhost --port 27017 -d test222 -c c21 - ...

  6. SpannableString

    http://blog.csdn.net/fengkuanghun/article/details/7904284 背景介绍 在开发应用过程中经常会遇到显示一些不同的字体风格的信息犹如默认的LockS ...

  7. 关于Unity中的世界坐标和局部坐标

    1.物体的局部坐标的方向(物体自身的方向) transform.forward. transform.right. transform.up 2.物体的世界坐标的方向 Vector3.forward. ...

  8. SQLSERVER中统计所有表的记录数

    SQLSERVER中统计所有表的记录数 利用系统索引表sysindexes中索引ID indid<1的行中的rows列存有该表的行数这一特点.    方法是利用隐藏未公开的系统存储过程sp_MS ...

  9. MBR:主引导记录:

    下面内容严重参考:百度百科: Main Boot Record)是位于磁盘最前边的一段引导(Loader)代码.它负责磁盘操作系统(DOS)对磁盘进行读写时分区合法性的判别.分区引导信息的定位,它由磁 ...

  10. Linux 安装 MongoDB数据库

    1下载: wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.7.tgz (下载较慢) 2.安装: mv mongodb-li ...