1. 利用协程可以实现方法延时调用
2. 继承CustomYieldInstruction类,可以自定义yield指令
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class DelayToInvoke
{
//内部类
private class TaskBehaviour : MonoBehaviour
{
}
private static TaskBehaviour taskBehaviour;
//静态构造函数
static DelayToInvoke()
{
GameObject gameObj = new GameObject("DelayToInvoke");
GameObject.DontDestroyOnLoad(gameObj);
taskBehaviour = gameObj.AddComponent<TaskBehaviour>();
}
//开始协程,非Mono类可调用
public static Coroutine StartCoroutine(IEnumerator routine)
{
if (routine == null)
return null;
return taskBehaviour.StartCoroutine(routine);
}
//终止协程
public static void StopCoroutine(ref Coroutine routine)
{
if (routine != null)
{
taskBehaviour.StopCoroutine(routine);
routine = null;
}
}
//延迟调用
public static Coroutine DelayToInvokeBySecond(Action action, float delaySeconds)
{
if (action == null)
return null;
return taskBehaviour.StartCoroutine(StartDelayToInvokeBySecond(action, delaySeconds));
}
//延迟调用
public static Coroutine DelayToInvokeByFrame(Action action, int delayFrames)
{
if (action == null)
return null;
return taskBehaviour.StartCoroutine(StartDelayToInvokeByFrame(action, delayFrames));
}
//循环调用
public static Coroutine ActionLoopByTime(float duration, float interval, Action action)
{
if (action == null)
return null;
if (duration <= 0 || interval <= 0 || duration < interval)
return null;
return taskBehaviour.StartCoroutine(StartActionLoopByTime(duration, interval, action));
}
//循环调用
public static Coroutine ActionLoopByCount(int loopCount, float interval, Action action)
{
if (action == null)
return null;
if (loopCount <= 0 || interval <= 0)
return null;
return taskBehaviour.StartCoroutine(StartActionLoopByCount(loopCount, interval, action));
}
//----------
private static IEnumerator StartDelayToInvokeBySecond(Action action, float delaySeconds)
{
if (delaySeconds > 0)
yield return new WaitForSeconds(delaySeconds);
else
yield return null;
action?.Invoke();
}
private static IEnumerator StartDelayToInvokeByFrame(Action action, int delayFrames)
{
if (delayFrames > 1)
{
for (int i = 0; i < delayFrames; i++)
{
yield return null;
}
}
else
yield return null;
action?.Invoke();
}
private static IEnumerator StartActionLoopByTime(float duration, float interval, Action action)
{
yield return new CustomActionLoopByTime(duration, interval, action);
}
private static IEnumerator StartActionLoopByCount(int loopCount, float interval, Action action)
{
yield return new CustomActionLoopByCount(loopCount, interval, action);
}
private class CustomActionLoopByTime : CustomYieldInstruction
{
private Action callback;
private float startTime;
private float lastTime;
private float interval;
private float duration;
public CustomActionLoopByTime(float _duration, float _interval, Action _callback)
{
//记录开始时间
startTime = Time.time;
//记录上一次间隔时间
lastTime = Time.time;
//记录间隔调用时间
interval = _interval;
//记录总时间
duration = _duration;
//间隔回调
callback = _callback;
}
//保持协程暂停返回true。让coroutine继续执行返回 false。
//在MonoBehaviour.Update之后、MonoBehaviour.LateUpdate之前,每帧都会查询keepWaiting属性。
public override bool keepWaiting
{
get
{
//此方法返回false表示协程结束
if (Time.time - startTime >= duration)
{
return false;
}
else if (Time.time - lastTime >= interval)
{
//更新上一次间隔时间
lastTime = Time.time;
callback?.Invoke();
}
return true;
}
}
}
private class CustomActionLoopByCount : CustomYieldInstruction
{
private Action callback;
private float lastTime;
private float interval;
private int curCount;
private int loopCount;
public CustomActionLoopByCount(int _loopCount, float _interval, Action _callback)
{
lastTime = Time.time;
interval = _interval;
curCount = 0;
loopCount = _loopCount;
callback = _callback;
}
public override bool keepWaiting
{
get
{
if (curCount > loopCount)
{
return false;
}
else if (Time.time - lastTime >= interval)
{
//更新上一次间隔时间
lastTime = Time.time;
curCount++;
callback?.Invoke();
}
return true;
}
}
}
}
本文来自博客园,作者:萧然CS,转载请注明原文链接:https://www.cnblogs.com/z-c-s/p/15112873.html
浙公网安备 33010602011771号