对Unity协程理解(二):自己实现一个简单的协程功能

1.实现协程功能需要对C#关键词Yield进行理解。(1)yield迭代器会暂停,直到下次调用MoveNext。此处可以做一些处理,来决定是暂停一帧还是暂停多少秒 (2)当MoveNext返回False时该迭代模块会结束。
实现代码如下:

1.当我们在Unity中随便写个协程方法比如:yield return myTest() 和yield return null 效果一样都是暂停一帧。
这是由于c#关键字yield。当执行到yield的时候会暂停,直到下一次调用MoveNext,才会继续往下执行。
 private IEnumerator Test()
    {
        Debug.Log("------Time1:" + Time.realtimeSinceStartup);
        Debug.Log("------Time2:" + Time.realtimeSinceStartup);
        yield return  new Mytest();
        Debug.Log("------Time3:"+Time.realtimeSinceStartup);
    }
	class  Mytest
	{  
	}
因此从yield return new myTest() 也是暂停一帧来看,可以判断出正常情况下Unity每一帧都回调用MoveNext。
2.于是写了第二个类测试:当moveNext返回时true 时,一直回调用Unity会一直处理该IEnumator当MoveNext=false时移除

  public class MyTest2 : IEnumerator
{
    private Action callBack = null;
    private float endTime;

    public MyTest2 (float time, Action callBack)
    {
        this.callBack = callBack;
        endTime = Time.realtimeSinceStartup + time;
    }

    public bool MoveNext()
    {
        return Time.realtimeSinceStartup < endTime;
    }
    public void Reset()
    {
        throw new System.NotImplementedException();
    }

    public object Current
    {
        get
        {
            if (callBack != null)
            {
                callBack();
            }
            return 1;
        }
    }
   3.自己实现一个简单的协程计时
     //C#中的迭代器
    class Program
    {
        static void Main(string[] args)
        {
            MyCoroutineManager co = new MyCoroutineManager();
            co.StartCoroutine(Test());
            while (true)
            {
                co.Update();
                Thread.Sleep(1);
            }
        }

        private static IEnumerator Test()
        {
            yield return null;
            Console.WriteLine("-----------");
            yield return new MyCoroutineWaitForSecond(5f);
            Console.WriteLine(DateTime.Now.ToString());
        }
    }

    class MyCoroutineManager
    {
        List<RoutineInfo> coroutineList = new List<RoutineInfo>();

        private void SetRoutineInfo(ref RoutineInfo info)
        {
            //info.iteror.Current 是在变动的 当暂停到 yield return null 时 currnet为null
            //当执行到 yield return new MyCoroutineWaitForSecond(5f); 此时不为空
            if (info.iteror.Current is MyCoroutineWaitForSecond)
            {
                info.yiel = info.iteror.Current as MyCoroutineWaitForSecond;
            }
        }

        public void Update()
        {
            List<RoutineInfo> keyToRemove = new List<RoutineInfo>();
            for (int i = 0; i < coroutineList.Count; i++)
            {
                RoutineInfo info = coroutineList[i];
                bool canMoveNext = false;
                if (info.yiel == null)
                {
                    canMoveNext = true;
                }
                else
                {
                    canMoveNext = info.yiel.DealWithYield();
                }
                if (!canMoveNext)
                {
                    continue;
                }
                //第一步执行yield return null 其MoveNext返回 true
                //第二步计时五秒后执行yield rturn wait。。。其返回false 这时候移除
                if (info.iteror.MoveNext())
                {
                    SetRoutineInfo(ref info);
                }
                else
                {
                    keyToRemove.Add(info);
                }
               
            }
            for (int i = 0; i < keyToRemove.Count; i++)
            {
                coroutineList.Remove(keyToRemove[i]);
            }
        }

        public void StartCoroutine(IEnumerator co)
        {
            if (co == null)
                return;
            RoutineInfo info = new RoutineInfo();
            info.iteror = co;
            SetRoutineInfo(ref info);
            coroutineList.Add(info);
        }
    }

    class RoutineInfo
    {
        public YieldFather yiel;
        public IEnumerator iteror;
    }
    abstract class YieldFather
    {
        public abstract bool DealWithYield();
    }
    class MyCoroutineWaitForSecond : YieldFather
    {
        public MyCoroutineWaitForSecond(float waitTime)
        {
            this.waitTime = waitTime;
            beginTime = DateTime.Now;
        }
        private float waitTime = 0;
        private DateTime beginTime;
        public override bool DealWithYield()
        {
            return (DateTime.Now - beginTime).TotalSeconds >= waitTime;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值