はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity】MonoBehaviourを継承していないクラスでコルーチンを使う(コールバックも)

はじめに

今回はMonoBehaviourを継承していないクラスでコルーチンを使う方法についての記事になります!

加えてその際にコールバックでやや手間取ってしまったので、そちらについても触れたいと思います。

MonoBehaviourとコルーチン

UnityのコルーチンといえばIEnumeratorを返すメソッドを指しています。

ただIEnumeratorインターフェイス自体はSystem.Collections名前空間内にあるので、そもそもUnity独自の機能ではありません。

しかし、コルーチンを使うためのStartCoroutineメソッドはMonoBehaviourクラスのメンバなので、MonoBehaviourを継承しなければなりません。

簡単にまとめると、StartCoroutineMonoBehaviourを継承していないと使えないので、コルーチンが使えないということになります。

コルーチンをIObservable化する

UniRxというアセットを用いることで、コルーチンをIObservable化することができ、MonoBehaviourを継承していない状態でもコルーチンを使えるようにすることができます

またUniRxを導入しなきゃいけないじゃん!と思うかもしれませんが、他にもたくさんの便利機能があるので、一度検討してみてはどうでしょうか。

コルーチンからObservableを作るには、Observable.FromCoroutineメソッドを使うことで実現することができます。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

using UniRx;            //こちらを忘れずにする

public class Hoge
{
    /// <summary>
    /// コルーチンを利用する側
    /// </summary>
    public void UseCoroutine()
    {
        //コルーチンをIObsavable化することでMonoBehaviorを継承する必要がない
        Observable.FromCoroutine(Coroutine)
            .Subscribe(_ => Debug.Log("コルーチン終了後に実行する処理"));
    }

    /// <summary>
    /// コルーチン
    /// </summary>
    private IEnumerator Coroutine()
    {
        Debug.Log("Start");
        yield return new WaitForSeconds(1);
        Debug.Log("End");
    }
}

FromCoroutineの引数はコルーチンにすればOKです。

コールバックを入れる

上のやり方にコールバックも実装してみたいと思います。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

using UniRx;            //こちらを忘れずにする
using System;           //こちらも忘れずにする

public class Hoge
{
    /// <summary>
    /// コルーチンを利用する側
    /// </summary>
    public void UseCoroutine()
    {
        //コルーチンをIObsavable化することでMonoBehaviorを継承する必要がない
        Observable.FromCoroutine<string>(observer => Coroutine(observer))
            .Subscribe(comment => Debug.Log(comment));
    }

    /// <summary>
    /// コルーチン
    /// </summary>
    private IEnumerator Coroutine(IObserver<string> observer)
    {
        Debug.Log("Start");
        yield return new WaitForSeconds(1);
        Debug.Log("End");

        observer.OnNext("コールバック");  //OnNextでSubscribeしたコールバックを実行する
        observer.OnCompleted();           //observerを完了する
    }
}

このようにすることでコールバックを実現することができました。

細かい説明はこちらの記事をご覧ください。
はじめてのUniRx

さいごに

これでMonoBehaviourを継承していないクラスでコルーチンを使うことができました。
コルーチンは本当に使い勝手がいいので、是非うまく利用しちゃいましょう!