[个人框架 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++;
}
}
}