diff --git a/Assets/Scripts/Utilities/CoroutineManager.cs b/Assets/Scripts/Utilities/CoroutineManager.cs new file mode 100644 index 00000000..ec52f9dc --- /dev/null +++ b/Assets/Scripts/Utilities/CoroutineManager.cs @@ -0,0 +1,57 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace SanAndreasUnity.Utilities +{ + public class CoroutineManager : StartupSingleton + { + private static CoroutineRunner m_coroutineRunner = new CoroutineRunner(); + + +#if UNITY_EDITOR + [UnityEditor.InitializeOnLoadMethod] + static void InitOnLoad() + { + UnityEditor.EditorApplication.update -= EditorUpdate; + UnityEditor.EditorApplication.update += EditorUpdate; + } + + static void EditorUpdate() + { + if (!F.IsAppInEditTime) + return; + + m_coroutineRunner.Update(); + } +#endif + + void Update() + { + m_coroutineRunner.Update(); + } + + public static CoroutineInfo Start(IEnumerator coroutine) + { + return m_coroutineRunner.StartCoroutine(coroutine, null, null); + } + + public static CoroutineInfo Start( + IEnumerator coroutine, + System.Action onFinishSuccess, + System.Action onFinishError) + { + return m_coroutineRunner.StartCoroutine(coroutine, onFinishSuccess, onFinishError); + } + + public static void Stop(CoroutineInfo coroutineInfo) + { + m_coroutineRunner.StopCoroutine(coroutineInfo); + } + + public static bool IsRunning(CoroutineInfo coroutineInfo) + { + return m_coroutineRunner.IsCoroutineRunning(coroutineInfo); + } + } +} diff --git a/Assets/Scripts/Utilities/CoroutineManager.cs.meta b/Assets/Scripts/Utilities/CoroutineManager.cs.meta new file mode 100644 index 00000000..822e5856 --- /dev/null +++ b/Assets/Scripts/Utilities/CoroutineManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 81bcbcc6c7d0163408eea6ffa3732506 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Utilities/CoroutineRunner.cs b/Assets/Scripts/Utilities/CoroutineRunner.cs new file mode 100644 index 00000000..b935f104 --- /dev/null +++ b/Assets/Scripts/Utilities/CoroutineRunner.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace SanAndreasUnity.Utilities +{ + public class CoroutineInfo + { + private static long s_lastId = 0; + public long Id { get; } = ++s_lastId; + + public IEnumerator coroutine { get; } + public System.Action onFinishSuccess { get; } + public System.Action onFinishError { get; } + + public CoroutineInfo(IEnumerator coroutine, Action onFinishSuccess, Action onFinishError) + { + this.coroutine = coroutine; + this.onFinishSuccess = onFinishSuccess; + this.onFinishError = onFinishError; + } + } + + public class CoroutineRunner + { + private List m_coroutines = new List(); + private List m_newCoroutines = new List(); + + + public CoroutineInfo StartCoroutine(IEnumerator coroutine, System.Action onFinishSuccess, System.Action onFinishError) + { + var coroutineInfo = new CoroutineInfo(coroutine, onFinishSuccess, onFinishError); + m_newCoroutines.Add(coroutineInfo); + return coroutineInfo; + } + + public void StopCoroutine(CoroutineInfo coroutineInfo) + { + if (null == coroutineInfo) + return; + + int index = m_coroutines.IndexOf(coroutineInfo); + if (index >= 0) + m_coroutines[index] = null; + + m_newCoroutines.Remove(coroutineInfo); + } + + public bool IsCoroutineRunning(CoroutineInfo coroutineInfo) + { + if (null == coroutineInfo) + return false; + + return m_coroutines.Contains(coroutineInfo); + } + + public void Update() + { + m_coroutines.RemoveAll(c => null == c); + + m_coroutines.AddRange(m_newCoroutines); + m_newCoroutines.Clear(); + + for (int i = 0; i < m_coroutines.Count; i++) + { + this.UpdateCoroutine(m_coroutines[i], i); + } + + } + + void UpdateCoroutine(CoroutineInfo coroutine, int coroutineIndex) + { + bool isFinished = false; + bool isSuccess = false; + System.Exception failureException = null; + + try + { + if (!coroutine.coroutine.MoveNext()) + { + isFinished = true; + isSuccess = true; + } + } + catch (System.Exception ex) + { + isFinished = true; + isSuccess = false; + failureException = ex; + Debug.LogException(ex); + } + + if (isFinished) + { + m_coroutines[coroutineIndex] = null; + + if (isSuccess) + F.RunExceptionSafe(coroutine.onFinishSuccess); + else + F.RunExceptionSafe(() => coroutine.onFinishError(failureException)); + } + } + } +} diff --git a/Assets/Scripts/Utilities/CoroutineRunner.cs.meta b/Assets/Scripts/Utilities/CoroutineRunner.cs.meta new file mode 100644 index 00000000..38e5fafd --- /dev/null +++ b/Assets/Scripts/Utilities/CoroutineRunner.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 577a4c9d6ba16494f8bea1797e91fb73 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: