Unity Editorでコルーチンが使える「Editor Coroutines」の使い方をまとめました。
- Editor Coroutines?
- インストール
- EditorWindowでコルーチンを使う
- EditorCoroutineUtilityを直接使う
- オーナーを持たないEditiorCoroutineUtility.StartCoroutineOwnerless
- 参考
Unity2020.2.7f1
Editor Coroutines?
Editor Coroutinesはエディタでコルーチンを使うための機能です。
Unityの公式パッケージとして配布されています。
ランタイムで使うコルーチンはMonoBehaviourが必要ですが、Editor CoroutinesはMonoBehaviourに依存しない仕組みになっています。
要件はUnity2018.1以上で、Unity2020.2でパッケージが正式リリースになりました。
インストール
Editor CoroutinesはPackage Managerからインストールできます。
Package Managerの使い方は以下の記事にまとめていますので、必要に応じて参照してください。
EditorWindowでコルーチンを使う
それでは実際にEditor Coroutinesを使ってみます。
まずEditorWindowで使うには以下のようにEditorWindowの拡張メソッドとして定義されているStartCoroutine
とStopCoroutine
を使います。
using System.Collections; using Unity.EditorCoroutines.Editor; using UnityEditor; using UnityEngine; public class ExampleWindow : EditorWindow { private EditorCoroutine _coroutine; private void OnEnable() { // コルーチンを開始 _coroutine = this.StartCoroutine(LogTimeSinceStartup()); } private void OnDisable() { // コルーチンを停止 this.StopCoroutine(_coroutine); } [MenuItem("Window/Example")] private static void Open() { GetWindow<ExampleWindow>(); } private IEnumerator LogTimeSinceStartup() { while (true) { Debug.Log(Time.realtimeSinceStartup); yield return null; } } }
使い勝手はランタイムのコルーチンと同様です。
EditorCoroutineUtilityを直接使う
さて前節ではEditorWindowの拡張メソッドを使いました。
この拡張メソッドのStopCoroutine()
の中ではEditorCoroutineUtilityが使用されており、以下のようにこれを直接使うこともできます。
using System.Collections; using Unity.EditorCoroutines.Editor; using UnityEditor; using UnityEngine; public class ExampleWindow : EditorWindow { private EditorCoroutine _coroutine; private void OnEnable() { // Ownerを指定してコルーチンを開始 // OwnerがGCで回収された際にコルーチンが走ってたら止まる _coroutine = EditorCoroutineUtility.StartCoroutine(LogTimeSinceStartup(), this); } private void OnDisable() { // 本当はEditorWindowCoroutineExtension.StopCoroutine()を参考に制御するべき EditorCoroutineUtility.StopCoroutine(_coroutine); } [MenuItem("Window/Example")] private static void Open() { GetWindow<ExampleWindow>(); } private IEnumerator LogTimeSinceStartup() { while (true) { Debug.Log(Time.realtimeSinceStartup); yield return null; } } }
注意点として、EditorCoroutineUtility.StartCoroutine()
の第二引数には何かしらのobjectを与えます。
これがGCで回収されたときにもしコルーチンが走ったままだったら、その時点でコルーチンが止まります。
しかしGCのタイミングは制御しづらいので実際には上の例のようにEditorCoroutineUtility.StopCoroutine()
で止めたほうがよさそうです。
またコメントにも書きましたが、EditorCoroutineUtility.StopCoroutine()
の部分はもう少し異常系の対応を入れるべきです。
前節の拡張メソッドEditorWindowCoroutineExtension.StopCoroutine()
ではこのあたりの制御がされているので参考にして実装するとよさそうです。
オーナーを持たないEditiorCoroutineUtility.StartCoroutineOwnerless
さて前節のEditorCoroutineUtility.StartCoroutine()
は第二引数に何かしらのobjectを与えました。
EditiorCoroutineUtility.StartCoroutineOwnerless
を使うと、これを指定しないでコルーチンを開始できます。
この場合、コルーチンが勝手に停止することはないので自身で停止する必要があります。
using System.Collections; using Unity.EditorCoroutines.Editor; using UnityEditor; using UnityEngine; public class ExampleWindow : EditorWindow { private EditorCoroutine _coroutine; private void OnEnable() { // Ownerなしでコルーチンを開始 _coroutine = EditorCoroutineUtility.StartCoroutineOwnerless(LogTimeSinceStartup()); } private void OnDisable() { EditorCoroutineUtility.StopCoroutine(_coroutine); } [MenuItem("Window/Example")] private static void Open() { GetWindow<ExampleWindow>(); } private IEnumerator LogTimeSinceStartup() { while (true) { Debug.Log(Time.realtimeSinceStartup); yield return null; } } }