using System; using System.Collections.Generic; using UnityEngine; namespace DepthFirstScheduler { /// /// UniRxのMainThreadDispatcherを参考にした。 /// * https://github.com/neuecc/UniRx/blob/master/Assets/Plugins/UniRx/Scripts/UnityEngineBridge/MainThreadDispatcher.cs /// public class MainThreadDispatcher : MonoBehaviour { [Header("Debug")] public int TaskCount; IEnumerable Ancestors(Transform t) { yield return t; if (t.parent != null) { foreach (var x in Ancestors(t.parent)) { yield return x; } } } private void Update() { TaskCount = Scheduler.MainThread.UpdateAndGetTaskCount(); } static MainThreadDispatcher instance; static bool initialized; static bool isQuitting = false; public static bool IsInitialized { get { return initialized && instance != null; } } [ThreadStatic] static object mainThreadToken; public static MainThreadDispatcher Instance { get { Initialize(); return instance; } } public static void Initialize() { if (!initialized) { #if UNITY_EDITOR if (!Application.isPlaying) { return; } #endif MainThreadDispatcher dispatcher = null; try { dispatcher = GameObject.FindObjectOfType(); } catch { // Throw exception when calling from a worker thread. var ex = new Exception( "DepthFirstScheduler requires a MainThreadDispatcher component created on the main thread." + " Make sure it is added to the scene before calling DepthFirstScheduler from a worker thread."); UnityEngine.Debug.LogException(ex); throw ex; } if (isQuitting) { // don't create new instance after quitting // avoid "Some objects were not cleaned up when closing the scene find target" error. return; } if (dispatcher == null) { // awake call immediately from UnityEngine new GameObject("MainThreadDispatcher").AddComponent(); } else { dispatcher.Awake(); // force awake } } } public static bool IsInMainThread { get { return (mainThreadToken != null); } } void Awake() { if (instance == null) { Debug.Log("Initialize UniTask.MainThredDispatcher"); instance = this; mainThreadToken = new object(); initialized = true; DontDestroyOnLoad(gameObject); } else { if (this != instance) { Debug.LogWarning("There is already a MainThreadDispatcher in the scene."); } } } void OnDestroy() { if (instance == this) { instance = GameObject.FindObjectOfType(); initialized = instance != null; } if (Scheduler.SingleWorkerThread != null) { Scheduler.SingleWorkerThread.Dispose(); } } void OnApplicationQuit() { isQuitting = true; } } }