您的位置:首页 > 移动开发 > Unity3D

Unity 协程使用指南

2016-01-03 16:17 555 查看

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、UnifyWiki

2、维基百科
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: