(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

StartCoroutine(MonoBehaviour)を使わずにコルーチンを実行する【Unity】【エディタ拡張】


このエントリーをはてなブックマークに追加



この記事でのバージョン
Unity 2017.2.0f3


はじめに

Unityでは通常、コルーチン(Coroutine)を実行したい場合は以下のように、

MonoBehaviourのStartCoroutineを使って実行します。

private void Start () {
  //StartCoroutineを使ってコルーチンを実行
  StartCoroutine(DelayLog());
}

//0.5秒待ってからログを表示
private IEnumerator DelayLog(){
  Debug.Log("待ち開始……");
  yield return new WaitForSeconds(0.5f);
  Debug.Log("待ち終了!");
}

f:id:kan_kikuchi:20171214073408g:plain


しかし、エディタ拡張でMonoBehaviourないけど、コルーチンを使いたい!という時もあります。

今回はそんな時に役立つ記事です!


IEnumerator. MoveNext

StartCoroutineを使わずにコルーチンを使いたい場合は、

IEnumerator型で変数を作成し、そのMoveNextを実行するだけ。


実際にやってみると以下のような感じ。

public class DelayLogWindow : EditorWindow {

  private static IEnumerator _iEnumerator = null;

  //=================================================================================
  //初期化
  //=================================================================================

  //メニューからウィンドウを表示
  [MenuItem("Window/Delay Log Window")]
  public static void Open (){
    DelayLogWindow.GetWindow (typeof(DelayLogWindow));
    EditorApplication.update += Update;
  }

  private void OnEnable (){
    EditorApplication.update += Update;
  }

  //=================================================================================
  //表示するGUIの設定
  //=================================================================================

  private void OnGUI(){
    if(GUILayout.Button ("実行")) {
      //コルーチンを作成
      _iEnumerator = DelayLog ();
    }
  }

  private static void Update(){
    if(_iEnumerator != null){
      //コルーチンを実行
      _iEnumerator.MoveNext();
    }
  }

  //0.5秒待ってからログを表示
  private IEnumerator DelayLog(){
    Debug.Log("待ち開始……");

    //エディタが開始されてからの時間を取得
    double timeSinceStartup = EditorApplication.timeSinceStartup;

    //0.5秒経過するまで待機
    while (EditorApplication.timeSinceStartup - timeSinceStartup < 0.5f) {
      yield return 0;
    }

    Debug.Log("待ち終了!");
    _iEnumerator = null;
  }

}

f:id:kan_kikuchi:20171214081422g:plain


最初の例よりちょっと複雑になったように見えるかもしれませんが、重要なのは以下の2箇所だけです。

//コルーチンを作成
_iEnumerator = DelayLog ();
//コルーチンを実行
_iEnumerator.MoveNext();


あとはWaitForSecondsが使えないので、

EditorApplication.timeSinceStartupで経過時間を確認していたり、

OnGUIは常に実行され続けるわけではないので、

EditorApplication.updateを使って更新処理を行っていたりしています。


エディタ拡張でコルーチンが使えれば、

以下の記事のようにUnityWebRequestの送信も簡単に行えるようになります。

_enumerator = SendWebRequest(request, FinishConvert);
if(_enumerator != null){
  while (_enumerator.MoveNext()) {}
}
//変換リクエスト送信
private IEnumerator SendWebRequest(UnityWebRequest request, Action<bool, string> callback) {

//リクエスト送信
yield return request.SendWebRequest();

//リクエストが完了するまで待機
while(!request.isDone){
  yield return 0;
}


ただし、StartCoroutineを使わない場合は、

request.isDoneを見て送信が完了するまで待機する必要があります。