はなちるのマイノート

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

【Unity】StopCoroutineメソッドに潜まれた罠

はじめに

今回はStopCoroutineメソッドを使うにあたって注意しなければならないことについての記事になります!

コルーチンを止める方法として用意されているStopCoroutineメソッドですが、実はこのメソッドには3つの呼び出し方(オーバーロード)があることをご存じでしょうか。

ただこのオーバーロードを正しく使わなければ、うまく動かないことがあるのです。

まずはその3つの使い方を紹介した後、注意しなければならないことについて詳しくみていきたいと思います。

また早く結論が見たいかたは、目次からオーバーロードの説明を飛ばしていただいても全然OKです。

Stringを使ったStopCoroutine

まずはstring型の変数を引数にとるオーバーロードについてです。

using System.Collections;
using UnityEngine;

public class CoroutineTest : MonoBehaviour
{
    private IEnumerator Start()
    {
        StartCoroutine("SomeCoroutine");
        yield return new WaitForSeconds(1f);
        StopCoroutine("SomeCoroutine");
    }

    private IEnumerator SomeCoroutine()
    {
        int i = 0;
        while (true)
        {
            i++;
            Debug.Log(i);
            yield return new WaitForSeconds(.1f);
        }
    }
}

IEnumratorを使ったStopCoroutine

今度はIEnumratorインターフェイスを用いたオーバーロードについてです。

using System.Collections;
using UnityEngine;

public class CoroutineTest : MonoBehaviour
{
    IEnumerator _someCoroutine;

    private IEnumerator Start()
    {
        _someCoroutine = SomeCoroutine();
        StartCoroutine(_someCoroutine);
        yield return new WaitForSeconds(1f);
        StopCoroutine(_someCoroutine);
    }

    private IEnumerator SomeCoroutine()
    {
        int i = 0;
        while (true)
        {
            i++;
            Debug.Log(i);
            yield return new WaitForSeconds(.1f);
        }
    }
}

Coroutineを使ったStopCoroutine

名前がややこしいですが、MonoBehavior.Coroutineというクラスのインスタンスの参照を引数にとるオーバーロードがあります。

using System.Collections;
using UnityEngine;

public class CoroutineTest : MonoBehaviour
{
    Coroutine _someCoroutine;

    private IEnumerator Start()
    {
        _someCoroutine = StartCoroutine(SomeCoroutine());
        yield return new WaitForSeconds(1f);
        StopCoroutine(_someCoroutine);
    }

    private IEnumerator SomeCoroutine()
    {
        int i = 0;
        while (true)
        {
            i++;
            Debug.Log(i);
            yield return new WaitForSeconds(.1f);
        }
    }
}

注意しなければならないこと

先程の3つのオーバーロードの使用例ですが、なにか違和感を感じた方がもしかしたらいるのではないでしょうか。

その違和感は、StopCoroutineメソッドの種類によってStartCoroutineメソッドの使い方を変化させていたところです。

実はこれは公式にも表記されているのですが、StartCoroutineメソッドでstring型の引数を用いたら、StopCoroutineメソッドの引数は必ずstring型の引数を用いなければならないのです

これはIEnumratorでもCoroutineでも同様になります。

ダメな例

using System.Collections;
using UnityEngine;

public class CoroutineTest : MonoBehaviour
{
    private IEnumerator Start()
    {
        StartCoroutine(SomeCoroutine());
        yield return new WaitForSeconds(1f);
        StopCoroutine("SomeCoroutine");
    }

    private IEnumerator SomeCoroutine()
    {
        int i = 0;
        while (true)
        {
            i++;
            Debug.Log(i);
            yield return new WaitForSeconds(.1f);
        }
    }
}

これをやると永遠にコルーチンが止まりません…

さいごに

割と最初はこれは引っ掛かりやすい罠なような気がします。

もしうまく停止してなさそうな時は是非ここらへんをチェックしてみてください!