Unityの複数コルーチンを待つ(コールバック)方法

2021/01/25
カテゴリー: Unity


Unityで複数コルーチンが違うタイミングで処理が終わるときにすべてが終わったら違う処理をするというときに使えます。
今回はコールバック関数を使い、複数コルーチンの処理を待ち、完了したら次の処理を実行するプログラムを紹介いたします。

Itemオブジェクトを用意する

はじめに、処理時間がバラバラなItemオブジェクトを作っていきます。
Itemオブジェクトにつけるスクリプトはこちらです。
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class ItemController : MonoBehaviour
{
    [SerializeField] Text ItemText;
    [SerializeField] Image ItemImage;

    public IEnumerator ItemProcess(Action callback)
    {
        ItemText.text = "処理中";
        ItemImage.color = Color.red;
        yield return new WaitForSeconds(UnityEngine.Random.Range(2f, 4f));
        ItemText.text = "完了";
        ItemImage.color = Color.green;
        GetComponent<Animator>().SetBool("isPlay", false);
        callback.Invoke();
    }
}

このプログラムはItemProcess関数を呼び出すとテキストを"処理中"と表示し、Imageオブジェクトの色を赤にします。
ランダムで2秒から4秒待った後にテキストを"完了"にし、色をみどりにします。
その後アニメーションをストップし、コールバック関数を呼び出します。

ItemProcess関数を呼び出した様子がこちらです。


WaitObjオブジェクトを用意する

スクリプトはこちらです。
using UnityEngine;
using UnityEngine.UI;
public class WaitObjController : MonoBehaviour
{
    [SerializeField] Text WaitObjText;
    public void WaitObjProcess()
    {
        WaitObjText.text = "完了!";
        WaitObjText.color = Color.green;
    }
}

関数よばれたらテキストに"完了"を表示し、色を緑にする処理です。

Managerを作成し、コールバックを実装する

スクリプトはこちらです。
using System.Collections;
using UnityEngine;
public class Manager : MonoBehaviour
{
    [SerializeField] Transform itemParent;
    [SerializeField] ItemController itemPref;
    [SerializeField] WaitObjController waitObjController;
    IEnumerator Start()
    {
        int count = 0;
        void callback () => count++;
        int n = InsItem();
        yield return new WaitUntil(() => count == n);
        waitObjController.WaitObjProcess();

        int InsItem()
        {
            int i;
            for (i = 0; i < UnityEngine.Random.Range(2,6); i++)
            {
                var ins = Instantiate(itemPref, itemParent);
                StartCoroutine(ins.ItemProcess(callback));
            }
            return i;
        }
    }
}

Start関数をコルーチンにしてyieldを使えるようにします。
コールバック関数はただカウントアップするだけです。
InsItem関数でランダムな関数をItemのインスタンスを生成してcallback関数を引数にItemProcessを実行します。
yield return new WaitUntil(() => count == n);
によってcountがランダムでインスタンスが生成した回数になるまで処理を待ちます。
そして最後にWaitObjProcess関数を実行して終わります。
これによって複数コルーチンを待つ処理が実現できました。
実行した様子がこちらです。