public static void Initialize() { if (!initialized) { if (!Application.isPlaying) return; initialized = true; instance = new GameObject("MainThreadDispatcher").AddComponent<MainThreadDispatcher>(); DontDestroyOnLoad(instance); mainThreadToken = new object(); } }
public static IObservable <bool> EveryApplicationFocus() { return(MainThreadDispatcher.OnApplicationFocusAsObservable().AsObservable()); }
public IgnoreTimeScaleMainThreadScheduler() { MainThreadDispatcher.Initialize(); }
/// <summary> /// EveryLateUpdate calls from MainThreadDispatcher's OnLateUpdate. /// </summary> public static IObservable<long> EveryLateUpdate() { return MainThreadDispatcher.LateUpdateAsObservable().Scan(-1L, (x, y) => x + 1); }
/// <summary> /// EveryGameObjectUpdate calls from MainThreadDispatcher's Update. /// </summary> public static IObservable <long> EveryGameObjectUpdate() { return(MainThreadDispatcher.UpdateAsObservable().Scan(-1L, (x, y) => x + 1)); }
public void ScheduleQueueing <T>(ICancelable cancel, T state, Action <T> action) { MainThreadDispatcher.StartEndOfFrameMicroCoroutine(ImmediateAction(state, action, cancel)); }
public FixedUpdateMainThreadScheduler() { MainThreadDispatcher.Initialize(); }
void OnDestroy() { if (instance == this) { instance = GameObject.FindObjectOfType<MainThreadDispatcher>(); initialized = instance != null; /* // Although `this` still refers to a gameObject, it won't be found. var foundDispatcher = GameObject.FindObjectOfType<MainThreadDispatcher>(); if (foundDispatcher != null) { // select another game object Debug.Log("new instance: " + foundDispatcher.name); instance = foundDispatcher; initialized = true; } */ } }
static IObservable <T> RepeatUntilCore <T>(this IEnumerable <IObservable <T> > sources, IObservable <Unit> trigger, GameObject lifeTimeChecker) { return(Observable.Create <T>(observer => { var isFirstSubscribe = true; var isDisposed = false; var isStopped = false; var e = sources.AsSafeEnumerable().GetEnumerator(); var subscription = new SerialDisposable(); var schedule = new SingleAssignmentDisposable(); var gate = new object(); var stopper = trigger.Subscribe(_ => { lock (gate) { isStopped = true; e.Dispose(); subscription.Dispose(); schedule.Dispose(); observer.OnCompleted(); } }, observer.OnError); schedule.Disposable = Scheduler.CurrentThread.Schedule(self => { lock (gate) { if (isDisposed) { return; } if (isStopped) { return; } var current = default(IObservable <T>); var hasNext = false; var ex = default(Exception); try { hasNext = e.MoveNext(); if (hasNext) { current = e.Current; if (current == null) { throw new InvalidOperationException("sequence is null."); } } else { e.Dispose(); } } catch (Exception exception) { ex = exception; e.Dispose(); } if (ex != null) { stopper.Dispose(); observer.OnError(ex); return; } if (!hasNext) { stopper.Dispose(); observer.OnCompleted(); return; } var source = e.Current; var d = new SingleAssignmentDisposable(); subscription.Disposable = d; var repeatObserver = Observer.Create <T>(observer.OnNext, observer.OnError, self); if (isFirstSubscribe) { isFirstSubscribe = false; d.Disposable = source.Subscribe(repeatObserver); } else { MainThreadDispatcher.SendStartCoroutine(SubscribeAfterEndOfFrame(d, source, repeatObserver, lifeTimeChecker)); } } }); return new CompositeDisposable(schedule, subscription, stopper, Disposable.Create(() => { lock (gate) { isDisposed = true; e.Dispose(); } })); })); }
static void DomainCleanup() { initialized = false; isQuitting = false; instance = null; }
public static Coroutine WhenAll(IEnumerable <LazyTask> tasks) { Coroutine[] coroutines = (from x in tasks select x.Start()).ToArray(); return(MainThreadDispatcher.StartCoroutine(WhenAllCore(coroutines))); }
public void ScheduleQueueing <T>(ICancelable cancel, T state, Action <T> action) { MainThreadDispatcher.Post(Scheduler.IgnoreTimeScaleMainThreadScheduler.QueuedAction <T> .Instance, Tuple.Create <ICancelable, T, Action <T> >(cancel, state, action)); }
public IgnoreTimeScaleMainThreadScheduler() { MainThreadDispatcher.Initialize(); this.scheduleAction = new Action <object>(this.Schedule); }
public void ScheduleQueueing <T>(ICancelable cancel, T state, Action <T> action) { MainThreadDispatcher.StartFixedUpdateMicroCoroutine(this.ImmediateAction <T>(state, action, cancel)); }
IEnumerator DelayAction(TimeSpan dueTime, Action action) { yield return(new WaitForSeconds((float)dueTime.TotalSeconds)); MainThreadDispatcher.Post(action); }
void Awake() { instance = this; initialized = true; }
static void DestroyDispatcher(MainThreadDispatcher aDispatcher) { if (aDispatcher != instance) { // Try to remove game object if it's empty var components = aDispatcher.gameObject.GetComponents<Component>(); if (aDispatcher.gameObject.transform.childCount == 0 && components.Length == 2) { if (components[0] is Transform && components[1] is MainThreadDispatcher) { Destroy(aDispatcher.gameObject); } } else { // Remove component MonoBehaviour.Destroy(aDispatcher); } } }
public static Coroutine WhenAll(IEnumerable <LazyTask> tasks) { Coroutine[] coroutines = Enumerable.ToArray <Coroutine>(Enumerable.Select <LazyTask, Coroutine>(tasks, (LazyTask x) => x.Start())); return(MainThreadDispatcher.StartCoroutine(LazyTask.WhenAllCore(coroutines))); }
public void ScheduleQueueing <T>(ICancelable cancel, T state, Action <T> action) { MainThreadDispatcher.Post(QueuedAction <T> .Instance, Tuple.Create(cancel, state, action)); }
// delay action is run in StartCoroutine // Okay to action run synchronous and guaranteed run on MainThread IEnumerator DelayAction(TimeSpan dueTime, Action action, ICancelable cancellation) { #if UNITY_EDITOR if (!ScenePlaybackDetector.IsPlaying) { var startTime = DateTimeOffset.UtcNow; while (true) { yield return(null); if (cancellation.IsDisposed) { break; } var elapsed = DateTimeOffset.UtcNow - startTime; if (elapsed >= dueTime) { MainThreadDispatcher.UnsafeSend(action); break; } } ; yield break; } #endif if (dueTime == TimeSpan.Zero) { yield return(null); // not immediately, run next frame if (cancellation.IsDisposed) { yield break; } MainThreadDispatcher.UnsafeSend(action); } else if (dueTime.TotalMilliseconds % 1000 == 0) { yield return(new WaitForSeconds((float)dueTime.TotalSeconds)); if (cancellation.IsDisposed) { yield break; } MainThreadDispatcher.UnsafeSend(action); } else { var startTime = Time.time; var dt = (float)dueTime.TotalSeconds; while (true) { yield return(null); if (cancellation.IsDisposed) { break; } var elapsed = Time.time - startTime; if (elapsed >= dt) { MainThreadDispatcher.UnsafeSend(action); break; } } } }
public EndOfFrameMainThreadScheduler() { MainThreadDispatcher.Initialize(); }
public MainThreadScheduler() { MainThreadDispatcher.Initialize(); scheduleAction = new Action <object>(Schedule); }
public static Coroutine WhenAll(IEnumerable <LazyTask> tasks) { var coroutines = tasks.Select(x => x.Start()).ToArray(); return(MainThreadDispatcher.StartCoroutine(WhenAllCore(coroutines))); }
// I can't avoid Unity 5.3's uNET weaver bug, pending... //public static IObservable<T> SubscribeOnMainThread<T>(this IObservable<T> source, MainThreadDispatchType dispatchType) //{ // switch (dispatchType) // { // case MainThreadDispatchType.Update: // return source.SubscribeOnMainThread(); // faster path // // others, bit slower // case MainThreadDispatchType.FixedUpdate: // return new UniRx.Operators.SubscribeOnMainThreadObservable<T>(source, EveryFixedUpdate().Take(1)); // case MainThreadDispatchType.EndOfFrame: // return new UniRx.Operators.SubscribeOnMainThreadObservable<T>(source, EveryEndOfFrame().Take(1)); // case MainThreadDispatchType.GameObjectUpdate: // return new UniRx.Operators.SubscribeOnMainThreadObservable<T>(source, MainThreadDispatcher.UpdateAsObservable().Select(_ => 0L).Take(1)); // case MainThreadDispatchType.LateUpdate: // return new UniRx.Operators.SubscribeOnMainThreadObservable<T>(source, MainThreadDispatcher.LateUpdateAsObservable().Select(_ => 0L).Take(1)); // case MainThreadDispatchType.AfterUpdate: // return new UniRx.Operators.SubscribeOnMainThreadObservable<T>(source, EveryAfterUpdate().Take(1)); // default: // throw new ArgumentException("type is invalid"); // } //} public static IObservable<bool> EveryApplicationPause() { return MainThreadDispatcher.OnApplicationPauseAsObservable().AsObservable(); }
public MainThreadScheduler() { MainThreadDispatcher.Initialize(); scheduleAction = Schedule; }
public MainThreadScheduler() { MainThreadDispatcher.Initialize(); }
public static void Initialize() { if (!initialized) { #if UNITY_EDITOR // Don't try to add a GameObject when the scene is not playing. Only valid in the Editor, EditorView. if (!ScenePlaybackDetector.IsPlaying) return; #endif MainThreadDispatcher dispatcher = null; try { dispatcher = GameObject.FindObjectOfType<MainThreadDispatcher>(); } catch { // Throw exception when calling from a worker thread. var ex = new Exception("UniRx requires a MainThreadDispatcher component created on the main thread. Make sure it is added to the scene before calling UniRx 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) { instance = new GameObject("MainThreadDispatcher").AddComponent<MainThreadDispatcher>(); } else { instance = dispatcher; } DontDestroyOnLoad(instance); mainThreadToken = new object(); initialized = true; } }
/// <summary>AutoStart observable as coroutine.</summary> public static Coroutine StartAsCoroutine <T>(this IObservable <T> source, Action <T> onResult, Action <Exception> onError, CancellationToken cancel = default(CancellationToken)) { return(MainThreadDispatcher.StartCoroutine(source.ToAwaitableEnumerator(onResult, onError, cancel))); }
void Awake() { if (instance == null) { instance = this; mainThreadToken = new object(); initialized = true; // Added for consistency with Initialize() DontDestroyOnLoad(gameObject); } else { if (cullingMode == CullingMode.Self) { Debug.LogWarning("There is already a MainThreadDispatcher in the scene. Removing myself..."); // Destroy this dispatcher if there's already one in the scene. DestroyDispatcher(this); } else if (cullingMode == CullingMode.All) { Debug.LogWarning("There is already a MainThreadDispatcher in the scene. Cleaning up all excess dispatchers..."); CullAllExcessDispatchers(); } else { Debug.LogWarning("There is already a MainThreadDispatcher in the scene."); } } }
/// <summary>publish OnNext(Unit) and OnCompleted() on application quit.</summary> public static IObservable <Unit> OnceApplicationQuit() { return(MainThreadDispatcher.OnApplicationQuitAsObservable().Take(1)); }
public static CoroutineAsyncBridge Start<T>(T awaitTarget) { var bridge = new CoroutineAsyncBridge(); MainThreadDispatcher.StartCoroutine(bridge.Run(awaitTarget)); return bridge; }