コルーチンを使う場合 MonoBehaviour クラスを継承している必要があり
またオブジェクトがアクティブである必要がある
色々制限があって面倒だったので、GlobalCoroutine
を作成しました
これは内部で CoroutineManager
を生成しており、特に意識することなく利用できる
使い方
private void Test() { // コルーチン開始 GlobalCoroutine.Play(C()); // コールバックを利用して終わりの検知もできる GlobalCoroutine.Play(C(), () => Debug.Log("end")); // 内部でコルーチンをキャッシュしているので key を指定すれば途中で停止もできる GlobalCoroutine.Play(C(), id: "key"); // コルーチンの停止 GlobalCoroutine.Stop("key"); } private IEnumerator C() { Debug.Log("begin"); yield return new WaitForSeconds(1f); yield return new WaitForSeconds(1f); Debug.Log("end"); }
コード
using System; using System.Collections; using UnityEngine; public static class GlobalCoroutine { private static readonly CoroutineManager _i; static GlobalCoroutine() { var obj = new GameObject("CoroutineManager"); _i = obj.AddComponent<CoroutineManager>(); GameObject.DontDestroyOnLoad(_i); } /// <summary> /// Coroutine を開始する /// </summary> public static void Play(IEnumerator e, Action end = null, string key = "") { _i.Play(e, end, key); } public static void Stop(string key) { _i.Stop(key); } public static void StopAll() { _i.StopAll(); } }
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; internal class CoroutineManager : MonoBehaviour { private Dictionary<string, Coroutine> _dic = new Dictionary<string, Coroutine>(); internal void Stop(string key) { if (!_dic.ContainsKey(key)) { Debug.LogWarning($"{key} not found"); return; } StopCoroutine(_dic[key]); _dic[key] = null; _dic.Remove(key); } internal void StopAll() { StopAllCoroutines(); } internal void Play(IEnumerator e, Action end = null, string key = "") { var isCache = !string.IsNullOrEmpty(key) && !_dic.ContainsKey(key); if (isCache) { end += () => { if (_dic.ContainsKey(key)) _dic.Remove(key); }; } var c = StartCoroutine(Coroutine(e, end)); if (isCache) { _dic.Add(key, c); } } private IEnumerator Coroutine(IEnumerator e, Action end = null) { yield return e; end?.Invoke(); } }