制御とコンピューターサイエンスの間

This is a blog to share codes and ideas for building robots/aeronautical systems

UnityのCoRoutineについて

CoRoutineとはUnity公式マニュアルによると

コルーチンとは実行を停止して Unity へ制御を戻し、ただし続行するときは停止したところから次のフレームで実行を継続することができる関数です。

ほへ?

CoRoutineの動作がわかりやすいスクリプト

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

public class HelloCoroutine : MonoBehaviour
{
    private int count = 0;

    // Use this for initialization
    void Start ()
    {
        Debug.Log("start");
        enabled = false;
        string str = "Hello World";
        StartCoroutine(IEnumeratorMethod(str));
        StartCoroutine(IEnumeratorMethod(str));

        enabled = true;
        Debug.Log("EndStart");
    }
    
    // Update is called once per frame
    void Update ()
    {
        Debug.Log("update");
    }


    public IEnumerator IEnumeratorMethod(string str)
    {
        Debug.Log("before");
        yield return null;
        Debug.Log("after");
        yield return null;

    }
}

f:id:kandaiwata:20180720113755p:plain

まず初めにyieldは英語で生産という意味がありますが、 諦めるや止めるという意味もあります。 処理を一旦ここで止めましょうということで意味で捉えることとします。

1 Loop目: Start()関数の中身がまず実行されます。 ちょっと待ってーやという感じでStartCoroutine(IEnumeratorMethod(str));が割り込んできます。 するとbeforeが出力されますが、 「うふふふ今回はここまで♡」みたいな感じでyield return null;で処理を中断します。 次のStartCoroutine(IEnumeratorMethod(str));も同様。 すると、Start()の最後にたどり着きEndstartを出力。 まだまだ続き、update()関数があるHz数分呼ばれます。(ここどうなっているんでしょう)

2 Loop目突入: CoRoutineで「うふふ次回のお楽しみ♡」みたいな感じで寸止めされた処理がありますよね? ここでafterが出力されます。

もう少し発展させます。次はStart()関数をIEnumeratorにしたいと思います。

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

public class HelloCoroutine : MonoBehaviour
{
    private int count = 0;

    // Use this for initialization
    IEnumerator Start ()
    {
        Debug.Log("----------Start----------");
        enabled = false;
        string str = "Hello World";
        yield return StartCoroutine(IEnumeratorMethod(str));
        count += 1;
        StartCoroutine(IEnumeratorMethod(str));

        enabled = true;
        Debug.Log("----------EndStart----------");
    }
    
    // Update is called once per frame
    void Update ()
    {
        Debug.Log("update");
    }


    public IEnumerator IEnumeratorMethod(string str)
    {
        Debug.Log(count);

        Debug.Log("before");
        yield return null;
        Debug.Log("after");
        yield return null;

    }
}

f:id:kandaiwata:20180720114901p:plain するとどうでしょう。 IEnumerator Start()とすると、Start()関数が終わるまでUpdate()が始まりません。

yield return と書いているので StartCoroutineが終わらせるまで帰らせてくれません。 yield return君は変態ですね。