【术】Unity中c#协程原理及实现

来源:互联网 发布:珠海生活 知乎 编辑:程序博客网 时间:2024/04/30 11:20

使用Unity的都知道Unity提供了协程的方式,使用协程能够使异步回调更加简洁方便。但是Unity的协程只有继承MonoBehaviour才能开启,也就是说,如果你想用,则必须存在一个全局类,其挂在GameObject上,并且为了让所有地方都能使用,这个GameObject不可以消除。
这个限制虽然不会带来太大麻烦,但只要了解Unity协程的实现原理,完全可以仿照Unity实现一套自己的协程管理类。
废话少说,直接上代码。

using System.Collections;using System.Collections.Generic;namespace Com.Coroutine{    public class Coroutine    {        internal IEnumerator m_Routine;        internal IEnumerator Routine        {            get { return m_Routine; }        }        internal Coroutine()        {        }        internal Coroutine(IEnumerator routine)        {            this.m_Routine = routine;        }        internal bool MoveNext()        {            var routine = m_Routine.Current as Coroutine;            if (routine != null)            {                if (routine.MoveNext())                {                    return true;                }                else if (m_Routine.MoveNext())                {                    return true;                }                else                {                    return false;                }            }            else if (m_Routine.MoveNext())            {                return true;            }            else            {                return false;            }        }    }    // use this as a template for functions like WaitForSeconds()    public class WaitForCount : Coroutine    {        int count = 0;        public WaitForCount(int count)        {            this.count = count;            this.m_Routine = Count();        }        IEnumerator Count()        {            while (--count >= 0)            {                System.Console.WriteLine(count);                yield return true;            }        }    }    // use this as the base class for enabled coroutines    public class CoroutineManager    {        internal List<Coroutine> m_Coroutines = new List<Coroutine>();        // just like Unity's MonoBehaviour.StartCoroutine        public Coroutine StartCoroutine(IEnumerator routine)        {            var coroutine = new Coroutine(routine);            m_Coroutines.Add(coroutine);            return coroutine;        }        // call this every frame        public void ProcessCoroutines()        {            for (int i = 0; i < m_Coroutines.Count; )            {                var coroutine = m_Coroutines[i];                if (coroutine.MoveNext())                {                    ++i;                }                else if (m_Coroutines.Count > 1)                {                    m_Coroutines[i] = m_Coroutines[m_Coroutines.Count - 1];                    m_Coroutines.RemoveAt(m_Coroutines.Count - 1);                }                else                {                    m_Coroutines.Clear();                    break;                }            }        }    }}

调用可以按照下面来进行。

public IEnumerator StepBy () {    Console.WriteLine("Hello from coroutine");    yield return true;    Console.WriteLine("This is another line");    yield return true;    Console.WriteLine("And the last line");    yield return new WaitForCount(5);    Console.WriteLine("Now I'm done");}
0 0