はなちるのマイノート

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

【Unity】公式パッケージ「Editor Coroutines」を利用してエディタ内でCoroutineを扱う事ができるようにする(内部実装で説明)

はじめに

今回は公式パッケージであるEditor Coroutinesについて紹介をしたいと思います。

docs.unity3d.com

概要

Editor Coroutinesエディタ内でCoroutineを扱う事ができるようにした公式パッケージです。

The Editor Coroutines package allows the user to start the execution of iterator methods within the Editor similar to how we handle Coroutines inside MonoBehaviour scripts during runtime.

// DeepL
Editor Coroutinesパッケージは、MonoBehaviourスクリプト内で実行時にCoroutineを扱うのと同様に、Editor内でイテレータメソッドの実行を開始できるようにするものです。

もう少し踏み込んで説明すると、StartCouroutineMonoBehaviorに定義されています。
github.com

つまりエディタ拡張等のMonoBehavior.StartCourutineを呼ぶ事ができない環境では、コルーチンが使えないというわけですね。

環境

Unity 2021.3.0f1
com.unity.editorcoroutines v1.0.0

Editor Coroutinesのインストール

公式パッケージであり、Package Managerからインストールすることが可能です。

Package Manager

Unityのバージョンが古く表示されない場合はcom.unity.editorcoroutines@1.0Add package from git URL...に打ち込めばいけるはずです。

使い方

ドキュメントも大して書かれていませんし、パッケージのコード量もそこまで大した事ないので内部実装を参照しながら調べていったほうが良いかと思います。

EditorWindowCoroutineExtension.cs

EditorWindowの拡張メソッドとしてStartCouroutineStopCoroutineが用意されています。

public static EditorCoroutine StartCoroutine(this EditorWindow window, IEnumerator routine)
public static void StopCoroutine(this EditorWindow window, EditorCoroutine coroutine)

Class EditorWindowCoroutineExtension | Package Manager UI website

// 使い方
public class SampleEditorWindow : EditorWindow
{
    private void Sample()
    {
        this.StartCoroutine(HogeCoroutine());
    }

    private IEnumerator HogeCoroutine()
    {
        yield return null;
    }
}

またthisで指定したEditorWindowと紐づいているようで、インスタンスが破棄されたら止まるようにできているっぽいですね。

StopCoroutineの引数はStartCoroutineの返り値を入れてあげてください。

EditorWaitForSeconds.cs

Suspends the EditorCoroutine execution for the given amount of seconds, using unscaled time.
The coroutine execution continues after the specified time has elapsed.

Class EditorWaitForSeconds | Package Manager UI website

// DeepL翻訳
EditorCoroutineの実行を、指定された秒数だけ、非スケール時間を使用して一時停止します。
指定された時間が経過した後、コルーチンの実行は継続されます。

EditorWaitForSecondsなるものが用意されているようですね。調べてみたところWaitForSecondsは正しく動作していなかったので、EditorWaitForSecondsを利用するようにしてください。

// 内部実装
public class EditorWaitForSeconds
{
    public float WaitTime { get; }
    
    public EditorWaitForSeconds(float time)
    {
        WaitTime = time;
    }
}
// 使い方
private IEnumerator HogeCoroutine()
{
    // こっちは動かない
    yield return new WaitForSeconds(1);
        
    // こっちを使う
    yield return new EditorWaitForSeconds(1);
}

EditorCoroutineUtility.cs

EditorCoroutineUtilityもありますが、EditorWindowを使うにあたっては基本的にEditorWindowCoroutineExtensionを利用すればよいと思います。

ownerを誰に紐づけるかを指定したい(ライフサイクルを誰に紐づけるか)場合はEditorCoroutineUtilityを使います。

public static EditorCoroutine StartCoroutine(IEnumerator routine, object owner)
public static EditorCoroutine StartCoroutineOwnerless(IEnumerator routine)
public static void StopCoroutine(EditorCoroutine coroutine)

Class EditorCoroutineUtility | Package Manager UI website

// 使い方
public class SampleEditorWindow : EditorWindow
{
    private void Sample()
    {
        EditorCoroutineUtility.StartCoroutine(HogeCoroutine(), this);
    }

    private IEnumerator HogeCoroutine()
    {
        yield return new EditorWaitForSeconds(1);
    }
}

これもStopCoroutineの引数はStartCoroutineの返り値を入れてあげればOKです。

ただownerを適切に設定しないと、最悪動き続ける可能性があるので注意してください。