[个人框架 C_Framework] DelayExecute,

2018-11-05  本文已影响0人  hh5460

开发过程中经常会遇到需要等待一段时间再执行某一个方法,或者循环执行某一个方法, 很多人第一时间想到的就是Invoke和InvokeRepeating,当然了,如果可以的话那么没有任何问题,而且推荐使用它们,但是有些情况可能不适合它们的使用条件,例如有ABCD 4个方法,它们是一个队列,A执行完B执行然后CD依次执行,中间等待各自的延迟,有人说,Invoke就可以啊,在A中InvokeB,在B中InvokeC...etc...我不是说这样不行,这样方法间的耦合太高且不优雅,而且假设A在执行过程中异常遇到错误中断,导致Invoke B 的代码段无法执行,那么后续就都无法执行了...
那么我对以上几种需求,用协程做了封装,那么可以做到

1.开启协程,延迟指定时间后执行一次,然后关闭协程,每个协程有自己的key标识
2.开启协程,依次执行队列ABCDEFG,中间有各自的延迟等待...当队列执行时有新的项目加入,则加入到对列尾,如果全部执行完成,关闭队列
3.开启协程,定时循环执行方法Func
4.开启协程,传入系统委托Func<object,bool>,直到条件满足后,即Func的方法返回值为True,执行Action
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;

public class DelayExecute : SingleFramework<DelayExecute>
{
    public Dictionary<int, Coroutine> dicCoroutines = new Dictionary<int, Coroutine>();  //协程管理

    Queue<DelayItem> DelayQueues = new Queue<DelayItem>();       //延迟队列

    public static void EnQueue(System.Action action,float delayTime)
    {
        Instance._EnQueue (new DelayItem (action, delayTime));
    }

    void _EnQueue(DelayItem item)
    {
        DelayQueues.Enqueue(item);
    }

    public static void TodoOnceDelay(Action action, float delayTime)
    {
        Instance.TodoOnceDelay(new DelayItem(action, delayTime));
    }

    //延迟执行
    void TodoOnceDelay(DelayItem delayItem)
    {
        Coroutine coroutine = StartCoroutine(DelayToDo(delayItem));  //开始协程烤肉
        dicCoroutines.Add(delayItem.CoroutineKey, coroutine);        //加入字典管理
    }

    IEnumerator DelayToDo(DelayItem delayItem)
    {
        yield return new WaitForSeconds(delayItem.DelayTime);        //延迟等待
        delayItem.DelayAction();                                     //执行方法
        StopCoroutine(dicCoroutines[delayItem.CoroutineKey]);        //停止烤肉
        dicCoroutines.Remove(delayItem.CoroutineKey);                //字典中移除烤肉
    }

    //循环执行                       委托         延迟时间        循环时间          //循环次数
    public static void TodoCircle(Action action, float delayTime, float circleTime, int circleNum)
    {
        Instance._TodoCircle(action, delayTime, circleTime, circleNum);
    }

    Coroutine coroutineCircle;
    //循环执行                       委托         延迟时间        循环时间          //循环次数
    void _TodoCircle(Action action, float delayTime, float circleTime, int circleNum)
    {
        coroutineCircle = StartCoroutine(CircleTodo(action, delayTime, circleTime, circleNum));
    }

    //循环执行                       委托         延迟时间        循环时间      //循环次数   0表示无限循环
    IEnumerator CircleTodo(Action action, float delayTime, float circleTime, int circleNum)
    {
        yield return new WaitForSeconds(delayTime);
        WaitForSeconds wfs = new WaitForSeconds(circleTime);
        if (circleNum == 0)
        {
            while (true)
            {
                if (action != null)
                {
                    action();
                }
                yield return wfs;
            }
        }
        else
        {
            for (int i = 0; i < circleNum; i++)
            {
                if (action != null)
                {
                    action();
                }
                yield return wfs;
            }
        }
        StopCoroutine(coroutineCircle);
    }


    //静态方法方便调用
    public static void StartDelayQueues()
    {
        Instance._StartDelayQueues();
    }

    Coroutine coroutineDelayQueues;
    //开始执行延迟队列
    void _StartDelayQueues()
    {
        coroutineDelayQueues = StartCoroutine(DelayToDoQueues());
    }

    //关闭队列
    public void StopDelayQueues()
    {
        StopCoroutine(coroutineDelayQueues);
    }

    IEnumerator DelayToDoQueues()
    {
        while (DelayQueues.Count != 0)
        {
            DelayItem delayItem = DelayQueues.Dequeue();
            yield return new WaitForSeconds(delayItem.DelayTime);        //延迟等待
            delayItem.DelayAction();                                     //执行方法
        }
        StopDelayQueues();
    }


    Coroutine coroutineDelayUntil;
    /// <summary>
    /// 延迟等待,直到条件满足退出
    /// </summary>
    /// <param name="func"></param>
    /// <param name="parameter"></param>
    /// <param name="actionWaitOver"></param>
    public void DelayUntil(Func<object, bool> func, object parameter, Action actionWaitOver)
    {
        coroutineDelayUntil = StartCoroutine(Delay_Until(func, parameter, actionWaitOver));
    }

    IEnumerator Delay_Until(Func<object, bool> func, object parameter, Action actionWaitOver)
    {
        yield return new WaitUntil(() =>
        {
            return func(parameter);
        });
        if (actionWaitOver != null)
        {
            actionWaitOver();
        }
        StopCoroutine(coroutineDelayUntil);
    }

    protected class DelayItem
    {
        public Action DelayAction;   //延迟执行委托
        public float DelayTime;   //延迟时间    
        public int CoroutineKey;      //作为键存入字典中,当延迟执行完毕后根据键获取当前当前协程消除

        static int IncrementKey = 0;     //静态自增量,不遇确保唯一

        public DelayItem(Action action, float time)
        {
            this.DelayAction = action;
            this.DelayTime = time;
            this.CoroutineKey = IncrementKey++;
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读