Unity 协程使用指南

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、维基百科

时间: 2024-10-15 15:26:21

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

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

记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield return ,就可以通过StartCoroutine调用了.后来也是一直稀里糊涂地用,上网google些基本都是例子,很少能帮助深入理解Unity协程的原理的. 本文只是从Unity的角度去分析理解协程的内部运行原理,而不是从C#底层的语法实现来介绍(后续有需要再进行介绍),一共分为三部分: 线程(

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

尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield return ,就可以通过StartCoroutine调用了.后来也是一直稀里糊涂地用,上网google些基本都是例子,很少能帮助深入理解Unity协程的原理的. 本文只是从Unity的角度去分析理解协程的内部运行原理

Unity 协程深入解析与原理

先来直接放一段代码 1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public class CoroutineTest : MonoBehaviour 6 { 7 8 void Start() 9 { 10 Debug.Log("Start Begin"); 11 12 CustomCoroutine = DelayPrint("Hi"

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

Unity协程(Coroutine)管理类--TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 在分享vp_Timer 中提到,没有继承的MonoBehaviour,没有Update,InVoke 和StartCoroutine的机制,vp_Timer就是提供了InVoke的机制,而且还可以统一管理.本篇D.S.Qiu要分享的TaskManager就是一个协程 管理类. TaskManager -- Unit

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

Unity协程(Coroutine)原理深入剖析再续 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 前面已经介绍过对协程(Coroutine)的认识和理解,主要讲到了Unity引擎在执行协程(Coroutine)的原理(Unity协程(Coroutine)原理深入剖析)和对协程(Coroutine)状态的控制(Unity协程(Coroutine)管理类--TaskManager工具分享),到这使用Coroutine的疑问就没有了,但是D

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

Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield return ,就可以通过StartCoroutine调用了.后来也是一直稀里糊涂地用,上网google些基本都是例子,很少能帮助深入理解Unit

Unity协程使用经验

[Unity协程使用经验] 1.协程的好处是,异步操作发起的地方和结束的地方可以统一在一个方法,这样就不用引入额外的成员变量来进行状态同步. 2.在一个协程中,StartCoroutine()和 yield return StartCoroutine()是不一样的. 前者仅仅是开始一个新的Coroutine,这个新的Coroutine和现有Coroutine并行执行.  后者是返回一个新的Coroutine,当这个新的Coroutine执行完毕后,才继承执行现有Coroutine. 3.由于协程

关于Unity协程(Coroutine)

协程官方doc解释A coroutine is a function that can suspend its execution(yield) until the given given YieldInstruction finishes. StartCoroutine开启协程 先执行协程中的代码 碰到yield return时控制权交给unity引擎 引擎继续做接下来的工作例如第一次yield return之后执行StartCoroutine下一行代码 直到满足yield指令的要求才会重新进

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

尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 在分享vp_Timer 中提到,没有继承的MonoBehaviour,没有Update,InVoke 和StartCoroutine的机制,vp_Timer就是提供了InVoke的机制,而且还可以统一管理.本篇D.S.Qiu要分享的TaskManager就是一个协程 管理类. TaskManager —— Unity3D Managed Coroutines with Start, Stop, Resume ,看