お世話になっております。
しゃまとんです。
Unityにはコルーチンという機能がありますが、GameObjectがInActiveな場合使うことができません。
自分自身がアクティブでも親がInActiveであれば、同様の状態になります。
例えば、ある画像を表示前にロードして切り替えておきたい…みたいなことがあるとします。
ただSpriteを差し替える対象のImageのゲームオブジェクトはfalseになっていてStartCoroutineできない。。。といった状況になるかもしれません。
基本的には自分の管理下でコルーチン制御するほうがいいと思うのですが、こういう場合にグローバルなコルーチンを作っておくことでそちらに処理を移譲することができます。
コードはこんな感じです。
ただ実行したいIEnumratorをもらって実行するだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
using System.Collections; using System.Collections.Generic; using UnityEngine; ///////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Coroutine for inactive or static class. /// </summary> ///////////////////////////////////////////////////////////////////////////////////////////////// public class GlobalCoroutine : MonoBehaviour { // singleton private static GlobalCoroutine instance; ///////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Run the specified routine. /// </summary> /// <param name="routine">Routine.</param> ///////////////////////////////////////////////////////////////////////////////////////////////// public static Coroutine Run(IEnumerator routine) { // check and create GameObject. if (instance == null) { GameObject obj = new GameObject(); obj.name = "GlobalCoroutine"; instance = obj.AddComponent<GlobalCoroutine>(); DontDestroyOnLoad(obj); } return instance.StartCoroutine(instance.routine(routine)); } ///////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// execute routine /// </summary> /// <param name="src">Source.</param> ///////////////////////////////////////////////////////////////////////////////////////////////// private IEnumerator routine(IEnumerator src) { yield return StartCoroutine(src); } } |
このクラスはシングルトンで一度生成したら以降はずっと使えるようにしました。なるべくnewしたくないので。
呼び出し側の例はこういう感じで。
1 2 3 4 5 6 7 8 9 10 11 12 |
private void sample() { GlobalCoroutine.Run(routine()); } private IEnumerator routine() { Debug.Log("1"); yield return null; Debug.Log("2"); yield return null; Debug.Log("3"); yield return null; } |
今回はサンプルで汎用的なダイアログを作って、シングルトンで使いまわすの想定して実装してみました。(ここでは処理は抜粋しています)
staticメソッド内でプレハブからインスタンス生成するのですが、StartCoroutineは使えないため処理を移譲しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
///////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Create this instance. /// </summary> ///////////////////////////////////////////////////////////////////////////////////////////////// public static Coroutine Create() { if (instance != null) { return null; } return GlobalCoroutine.Run(create()); } ///////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Create this instance. /// </summary> ///////////////////////////////////////////////////////////////////////////////////////////////// private static IEnumerator create() { var req = Resources.LoadAsync(AssetName); while (!req.isDone) { yield return null; } GameObject prefab = req.asset as GameObject; Instantiate(prefab); yield return null; } |
今回のサンプルは下記URLに置いておきました。
https://github.com/shamaton/GlobalCoroutine
確認動作させたものはこちらです。
どうにもならんときに使えるかもです。
以上です。