|
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- namespace SUISS.Cloud
- {
- public class CloudRequestRunner
- {
- private class CoroutineWapper : CustomYieldInstruction
- {
- private bool _isRunning;
-
- private IEnumerator _innerRoutine;
-
- private CloudRequestRunner _scheduler;
-
- private MonoBehaviour _executor;
-
- public override bool keepWaiting => _isRunning;
-
-
- public CoroutineWapper(IEnumerator routine, CloudRequestRunner scheduler)
- {
- _scheduler = scheduler;
- _executor = _scheduler.Executor;
- _innerRoutine = routine;
- if (_executor != null)
- {
- _isRunning = true;
- _executor.StartCoroutine(Routine(routine));
- }
- }
-
- private IEnumerator Routine(IEnumerator routine)
- {
- while (routine.MoveNext())
- {
- object yielded = routine.Current;
- if (yielded != null && !_scheduler.IsSupportedYieldable(yielded))
- {
- UnityEngine.Debug.LogWarning(string.Format("The coroutine '{0}' yielded '{1}' which is not supported by '{2}'!", _innerRoutine, yielded ?? "null", _scheduler));
- }
- yield return yielded;
- }
- _scheduler.OnRoutineCompleted(_innerRoutine);
- _isRunning = false;
- }
- }
-
- private class CloudRequestRunnerMonoBehaviour : MonoBehaviour
- {
- }
-
- private HashSet<IEnumerator> _runningRoutines = new HashSet<IEnumerator>();
-
- private MonoBehaviour _executor;
-
- private string _executorName;
-
- private static CloudRequestRunner _instance;
-
- private MonoBehaviour Executor
- {
- get
- {
- if (_executor == null)
- {
- UnityEngine.Debug.LogError($"{this} is going to create a second GameObject to run coroutines! (Is the app quitting?) Any coroutines running before this may not have been completed! I hope you never see this error! :(");
- CreateScheduleExecutor();
- _runningRoutines.Clear();
- }
- return _executor;
- }
- }
-
- private CloudRequestRunner()
- {
- _executorName = $"__CloudRequestRunner{UnityEngine.Random.Range(1000, 9999)}";
- CreateScheduleExecutor();
- }
-
- public static CustomYieldInstruction StartCoroutine(IEnumerator routine)
- {
- if (_instance == null)
- {
- _instance = new CloudRequestRunner();
- }
- return _instance.StartRoutine(routine);
- }
-
- private CustomYieldInstruction StartRoutine(IEnumerator routine)
- {
- if (_executor == null)
- {
- CreateScheduleExecutor();
- }
- if (_executor != null)
- {
- if (_runningRoutines.Contains(routine))
- {
- throw new Exception($"You are calling StartRoutine on a routine '{routine}' that was already started.");
- }
- _runningRoutines.Add(routine);
- return new CoroutineWapper(routine, this);
- }
- UnityEngine.Debug.LogError($"The schedule executor backing this scheduler is null! Can't start {routine}");
- return null;
- }
-
- private bool IsSupportedYieldable(object yieldable)
- {
- return yieldable == null || yieldable is WWW || yieldable is YieldInstruction || yieldable is CustomYieldInstruction;
- }
-
- private void CreateScheduleExecutor()
- {
- if (_executor == null)
- {
- GameObject gameObject = GameObject.Find(_executorName);
- if (gameObject == null)
- {
- gameObject = new GameObject();
- gameObject.name = _executorName;
- UnityEngine.Object.DontDestroyOnLoad(gameObject);
- }
- _executor = gameObject.GetComponent<MonoBehaviour>();
- if (_executor == null)
- {
- _executor = gameObject.AddComponent<CloudRequestRunnerMonoBehaviour>();
- }
- }
- }
-
- private void OnRoutineCompleted(IEnumerator routine)
- {
- _runningRoutines.Remove(routine);
- }
- }
- }
|