Unity--- 简单模仿一下原生协程的实现

先来看下测试代码 ...

 void Start()
    {
        CoroutineManager.Manager.StartCorouine(testWaitTime(1));
        CoroutineManager.Manager.StartCorouine(testWaitTime(2));
        //CoroutineManager.Manager.StartCorouine(testWaitNull()); //支持null
        //CoroutineManager.Manager.StartCorouine(testWaitCoroutine());//支持等待其他协程结束
    }
    void Update()
    {
        CoroutineManager.Manager.Update();
    }
    IEnumerator testWaitTime(int index)
    {
        print(index + " start wait...");
        yield return new MyWaitForSecond(2);
        print(index + " 2s after");
        yield return new MyWaitForSecond(2);
        print(index + " 4s after");
        print(index + " end");

    }
   
    IEnumerator testWaitNull()
    {
        for (int i = 0; i < 100; i++)
        {
            print(i);
            yield return null;
        }
    }

    IEnumerator testWaitCoroutine()
    {
        yield return CoroutineManager.Manager.StartCorouine(testWaitTime2());
        print("cool");
    }
    IEnumerator testWaitTime2()
    {
        yield return new MyWaitForSecond(3);
    }

可以看到,这个调度器可以像用waitForSendond那样 调度协程的运行。另外,还支持null和等待其他协程结束。

下面上实现

public abstract class MyYieldInstruction
{
    public abstract bool MoveNext();
}
public class MyWaitForSecond : MyYieldInstruction
{
    private float time;
    public MyWaitForSecond(float t) { time = t; }

    public override bool MoveNext()
    {
        return (time -= Time.deltaTime) > 0f;
    }
}
public class MyCoroutine : MyYieldInstruction//这个用来支持等待其他协程的协程 同时考虑可以把诸如停止标记之类的和协程管理有关的东西放在这里面,而字典里就以这个类的对象作为key 
{
    public MyCoroutine(IEnumerator e) { mRefrence = e; }
    private IEnumerator mRefrence;

    public override bool MoveNext()
    {
        return CoroutineManager.Manager.HasCoroutine(mRefrence);
    }
}

public class CoroutineManager
{
    public static CoroutineManager Manager = new CoroutineManager();
    Dictionary<IEnumerator, MyYieldInstruction> mIterDic = new Dictionary<IEnumerator, MyYieldInstruction>();
    //提供给外界开启协程的接口
    public MyCoroutine StartCorouine(IEnumerator iter)
    {
        //先运行到第一个yield处
        iter.MoveNext();
        //得到yield 返回的 指令对象
        MyYieldInstruction operation = (MyYieldInstruction)iter.Current;
        //加入字典 进行管理
        mIterDic.Add(iter, operation);
        return new MyCoroutine(iter);
    }
    public bool HasCoroutine(IEnumerator e)
    {
        MyYieldInstruction temp;
        return mIterDic.TryGetValue(e, out temp);
    }
    public void Update()
    {   //每帧进行遍历
        GoOnForeach(mIterDic.GetEnumerator());
    }
    //可以删除修改元素的遍历
    void GoOnForeach(IEnumerator dicIter)
    {
        while (dicIter.MoveNext())
        {
            var dicIterItem = (KeyValuePair<IEnumerator, MyYieldInstruction>)dicIter.Current;
  
                                          //指令对象结束
            if (dicIterItem.Value==null||!dicIterItem.Value.MoveNext())
            {
                //如果这个协程后面还有yield  就替换新的指令对象
                if (dicIterItem.Key.MoveNext())
                {
                    if (dicIterItem.Value != null)
                    {
                        GoOnForeach(dicIter);
                        mIterDic[dicIterItem.Key] = (MyYieldInstruction)dicIterItem.Key.Current;
                        break;
                    }                  
                }
                //否则 删除这个协程
                else
                {                  
                    GoOnForeach(dicIter);
                    mIterDic.Remove(dicIterItem.Key);
                    break;
                }
            }
        }
    }
}

注释里把要讲的全讲完了...

总之 为了搞懂协程的含义,这波不亏

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值