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. linux下查看cpu物理个数和逻辑个数

    hadoop@chw-desktop3:~$ cat /proc/cpuinfo processor   : 0 vendor_id   : GenuineIntel cpu family  : 15 ...

  2. Redis备份

    Redis SAVE命令用来创建备份当前Redis数据库. 语法 Redis SAVE命令的基本语法如下所示: 127.0.0.1:6379> SAVE 例子 下面给出的例子创建备份当前的数据库 ...

  3. 1 php protocolbuffers安装

    安装工具 yum install autoconf yum install libtool 安装protoc编译器 # cd /root/soft/protobuf- autogen.sh : if ...

  4. 使用python(command line)出现的ImportError: No module named 'xxx'问题

    当你在python.exe直接输入 import test 时报出importerror: no module named 'test' ,这个错误时由于路径问题,sys并没有找到你输入的这个文件 解 ...

  5. asp.net请求管道和页面生命周期

  6. 利用memcpy函数实现float到QByteArray的相互转化

    一.为什么要实现float到QByteArry之间的相互转化 在总线通讯过程中(例如串口通讯),总线上传输的是字节数组变量,即ByteArray型的变量,在Qt中即为QbyteArray型变量.总线发 ...

  7. 关于qt QWebKit/QWebview 使用心得

    当前项目为c/s客户端,采用qt4.8.7,需要使用仪表盘.折线图.柱状图等,曾经使用过qwt和自定义的图形控件,但是都不尽如人意.最近发现ECharts控件不错.为此就要在qt端使用web的技术.为 ...

  8. 谈谈mongodb,mysql的区别和具体应用场景

    最近对数据库比较感兴趣,于是就去研究了下部分相关热门的数据库. MySQL 关系型数据库. 在不同的引擎上有不同 的存储方式. 查询语句是使用传统的sql语句,拥有较为成熟的体系,成熟度很高. 开源数 ...

  9. mysql insert exists || mysql 判断数据是否存在

    情景如下: "今日前端忽然说句, 我需要做个判断, 不能重复收藏, 我犹如颈有寒冰不寒而栗, 于是思考我该怎么做?为什么她都思考到了我没有思考到这是我的工作啊" 思考后得到三种解决 ...

  10. pandas 的数据结构(Series, DataFrame)

    Pandas 讲解 Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的. Pandas 纳入了大量库和一些标 ...