namespace repeatCallUtility { using System; using System.Collections; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif public class RepeatCallData { //public int DelayFrame; public int DelayFramer; //public float DelayTime; public float DelayTimer; public int RepeatFrame = -1; public int RepeatFramer; public float RepeatTime = -1; public float RepeatTimer; public Action Action; public float InvokeCount = Mathf.Infinity; public float InvokeCounter = Mathf.Infinity; //public float InvokeFrame = Mathf.Infinity; //public float InvokeFramer = Mathf.Infinity; //public float InvokeTime = Mathf.Infinity; //public float InvokeTimer = Mathf.Infinity; } public class RepeatCall : MonoBehaviour { #region Config public static RepeatCall Instance { get { if (instance == null) { GameObject go = new GameObject("RepeatCall"); instance = go.AddComponent(); DontDestroyOnLoad(go); } return instance; } set { instance = value; } } private static RepeatCall instance; private static float DeltaTime { get { if (Application.isPlaying) { return Time.deltaTime; } else //�༭��ģʽ��ʹ�� { #if UNITY_EDITOR double deltaTime = EditorApplication.timeSinceStartup - LastTimeSinceStartup; LastTimeSinceStartup = EditorApplication.timeSinceStartup; return (float) deltaTime; #else throw new Exception(); #endif } } } private static double LastTimeSinceStartup; private static Dictionary RepeatCallDataDictionary = new Dictionary(); #if UNITY_EDITOR //�༭��ģʽ��ʹ�� private static Dictionary CallbackFunctionDictionary = new Dictionary(); private static Dictionary RepeatCallDataDictionaryForEditor = new Dictionary(); #endif #endregion public static object Call(RepeatCallData repeatCallData) { //repeatCallData.DelayFramer = repeatCallData.DelayFrame; //repeatCallData.DelayTimer = repeatCallData.DelayTime; repeatCallData.RepeatFramer = repeatCallData.RepeatFrame; repeatCallData.RepeatTimer = repeatCallData.RepeatTime; repeatCallData.InvokeCounter = repeatCallData.InvokeCount; //repeatCallData.InvokeFramer = repeatCallData.InvokeFrame; //repeatCallData.InvokeTimer = repeatCallData.InvokeTime; if (Application.isPlaying) { Coroutine coroutine = Instance.StartCoroutine(repeatCall(repeatCallData)); if (coroutine != null) { RepeatCallDataDictionary.Add(coroutine, repeatCallData); } return coroutine; } else { #if UNITY_EDITOR IEnumerator enumerator = repeatCall(repeatCallData); RepeatCallDataDictionaryForEditor.Add(enumerator, repeatCallData); EditorApplication.CallbackFunction callbackFunction = () => UpdateEnumerators(enumerator); CallbackFunctionDictionary.Add(enumerator, callbackFunction); callbackFunction.Invoke(); EditorApplication.update += callbackFunction; LastTimeSinceStartup = EditorApplication.timeSinceStartup; return enumerator; #else throw new Exception(); #endif } } public static void PauseRepeatCall(object obj) { if (Application.isPlaying) { Instance.StopCoroutine((Coroutine) obj); } else { #if UNITY_EDITOR EditorApplication.CallbackFunction callbackFunction = CallbackFunctionDictionary[(IEnumerator) obj]; EditorApplication.update -= callbackFunction; #endif } } public static void ResumeRepeatCall(object obj) { if (Application.isPlaying) { RepeatCallData repeatCallData = RepeatCallDataDictionary[(Coroutine) obj]; Call(repeatCallData); } else { #if UNITY_EDITOR RepeatCallData repeatCallData = RepeatCallDataDictionaryForEditor[(IEnumerator) obj]; Call(repeatCallData); #endif } } private static void UpdateEnumerators(IEnumerator enumerator) //�༭��ģʽ��ʹ�� { enumerator.MoveNext(); } private static IEnumerator repeatCall(RepeatCallData repeatCallData) { //Debug.Log(repeatCallData.DelayFramer + " " + repeatCallData.DelayTimer); if (repeatCallData.DelayFramer > 0) { while (repeatCallData.DelayFramer > 0) { repeatCallData.DelayFramer--; yield return null; } if (InvokeRepeatCall(repeatCallData)) { yield break; } } else if (repeatCallData.DelayTimer > 0) { yield return null; //����StartCoroutine��������ִ�е���һ��yield while (repeatCallData.DelayTimer > 0) { repeatCallData.DelayTimer -= DeltaTime; yield return null; } if (InvokeRepeatCall(repeatCallData)) { yield break; } } else { if (InvokeRepeatCall(repeatCallData)) { yield break; } else { yield return null; } if (repeatCallData.RepeatFramer > -1) { while (repeatCallData.RepeatFramer > 0) { repeatCallData.RepeatFramer--; yield return null; } repeatCallData.RepeatFramer = repeatCallData.RepeatFrame; if (InvokeRepeatCall(repeatCallData)) { yield break; } } else if (repeatCallData.RepeatTimer > -1) { while (repeatCallData.RepeatTimer > 0) { repeatCallData.RepeatTimer -= DeltaTime; yield return null; } repeatCallData.RepeatTimer = repeatCallData.RepeatTime; if (InvokeRepeatCall(repeatCallData)) { yield break; } } else { throw new Exception(); } } } private static bool InvokeRepeatCall(RepeatCallData repeatCallData) { repeatCallData.Action.Invoke(); if (--repeatCallData.InvokeCounter <= 0) { return true; } else { return false; } } } public class DelayCall { public static object Call(int delayFrame, Action action) { RepeatCallData repeatCallData = new RepeatCallData(); repeatCallData.DelayFramer = delayFrame; repeatCallData.InvokeCount = 1; repeatCallData.Action = action; return RepeatCall.Call(repeatCallData); } public static object Call(float delayTime, Action action) { RepeatCallData repeatCallData = new RepeatCallData(); repeatCallData.DelayTimer = delayTime; repeatCallData.InvokeCount = 1; repeatCallData.Action = action; return RepeatCall.Call(repeatCallData); } } public class WhileCall : MonoBehaviour { public static WhileCall Instance { get { if (instance == null) { GameObject go = new GameObject("WhileCall"); instance = go.AddComponent(); DontDestroyOnLoad(go); } return instance; } set { instance = value; } } private static WhileCall instance; public static void Call(Action action, Func func) { Instance.StartCoroutine(whileCall(action, func)); } private static IEnumerator whileCall(Action action, Func func) { while (!func.Invoke()) { yield return null; } action.Invoke(); } } public class EndOfFrameCall : MonoBehaviour { public static EndOfFrameCall Instance { get { if (instance == null) { GameObject go = new GameObject("EndOfFrameCall"); instance = go.AddComponent(); DontDestroyOnLoad(go); } return instance; } set { instance = value; } } private static EndOfFrameCall instance; public static void Call(Action action) { Instance.StartCoroutine(call(action)); } private static IEnumerator call(Action action) { yield return new WaitForEndOfFrame(); action.Invoke(); } } }