めーぷるのおもちゃばこ

- アイドルになりたいエンジニア女子の制作日記 -

【Unity】一定時間待ってから処理をする〜コルーチンの使い方〜

コルーチンを使うときにいつも調べるので備忘録として書いておこうと思います🐼

コルーチンとは

Unityで反復処理をしたい時や一定時間待ってから処理したいときにコルーチンを使用します。
一定時間待ってから処理をしたい場合、Invoke()を使うこともできますが、
呼び出す関数名を文字列で指定するので間違っていてもエラーが出なかったり、引数を渡せないなどのデメリットがあるのでコルーチンを使うのがグッドだったりします。
また、処理A→ちょっと待つ→処理B→ちょっと待つ→処理C みたいなことが一つの関数でできたり、処理を停止して再開したりもできるのでとても便利でスマートです。


コルーチンの書き方

基本の形

コルーチンはIEnumeratorを返す関数として書き、実行はStartCoroutine(コルーチン名)でコルーチン名を指定して実行します。
コルーチン名はコルーチン名()でもいけるし、"コルーチン名"でも実行できます。
処理の中断はyield return [処理を待つ時間]という形で書きます。処理を待つ時間はフレーム単位や秒数を指定することができます。
以下のように書きます。

void Start(){

    //コルーチンの実行
    StartCoroutine(Hoge());

    //もしくは
    StartCoroutine("Hoge");
}

private IEnumarator Hoge(){
    
    //行いたい処理

}

IEnumeratorというのは反復処理を返すインターフェイスらしいです。
コルーチンのためだけに使うものなのかと思ってましたがそうではないらしいです。
良くわかんないのでまた調べておきます。

一定時間待つ処理を入れる

コルーチンの基本の一定時間待ってから処理を行う方法です。

yield return new WaitForSeconds(秒数);

と書くことで渡した秒数ぶん待ってから、次の行からの処理を行うことができます。
コルーチンの関数の中に何度もかけるので、処理A→ちょっと待つ→処理B→ちょっと待つ→処理C ができます。

void Start(){

    //コルーチンの実行
    StartCoroutine("Hoge");
}

private IEnumarator Hoge(){
    
    text.text = "おはようございます";

    //1秒待つ
    yield return new WaitForSeconds(1.0f);

    //1秒待った後の処理
    text.text = "こんにちは";

    //1秒待つ
    yield return new WaitForSeconds(1.0f);

    //1秒待った後の処理
    text.text = "こんばんは";
}


上記のコードで以下のような感じになります。

f:id:maplesyrup-cs6:20190624114043g:plain
一定時間待つ処理


引数を渡して実行する

引数を渡して実行することもできます。引数を渡して実行するときは、

StartCoroutine(コルーチン名(引数1, 引数2));

という書き方で引数を渡せます。引数が一つの場合は以下のような書き方もできます。

StartCoroutine("コルーチン名", 引数);


実際には以下のように使用します。

void Start(){
    //コルーチンの実行
    StartCoroutine(Hoge(3));
}

private IEnumarator Hoge(int num){

    text.text = "数:" + num;
    yield return null;
}

ーーー

繰り返しの処理

yield return null;

↑は、コルーチンの処理を中断するときに使用するのですが、コルーチンの途中で書くと、そこで一旦処理を中断して次のフレームから再開されます。
以下のように繰り返しの中に書くと、フレームごとに処理が実行されます。

private IEnumarator Hoge(int num){

        for(int i = 0; i < num; i++){
            text.text = "数" + i;
            yield return null;
        }
}

↓数字が綺麗に増えてないですがGIFだからです...

f:id:maplesyrup-cs6:20190624164636g:plain
フレームごとに処理を行う

以下みたいな感じで徐々に値を変えたいときとかに。暗転などに使えたりしそうです。

f:id:maplesyrup-cs6:20190624163804g:plain
フレームごとに処理を行う



また、以下のようにyield return new WaitForSecondsを繰り返しの中に書くと、渡した秒数ごとに処理が繰り返されるので、1秒ごとにマテリアルを透明にしていくとか、そういった処理が可能になります。

private IEnumarator Hoge(int num){

        for(int i = 0; i < num; i++){
            text.text = "数:" + i;
            yield return new WaitForSeconds(1.0);
        }
}

f:id:maplesyrup-cs6:20190624163649g:plain
1秒ごとに処理を行う
ーーー

コルーチンの中で別のコルーチンの実行

コルーチンの中で別のコルーチンを実行することもできます。コルーチンの中から実行するときはこのように書きます。

yield return StartCoroutine(コルーチン名());


以下のようなかんじになります。

    private IEnumerator Hoge(){

        for(int i = 0; i < 4; i++){
            text.text = "数1: " + i;
            //コルーチンの中でコルーチンの実行
            yield return StartCoroutine(Hoge2());    
        }
    }

    private IEnumerator Hoge2(){

        for(int i = 0; i < 4; i++){
            text2.text = "数2: " + i;
            yield return new WaitForSeconds(1.0f);
        }

    }

f:id:maplesyrup-cs6:20190624171823g:plain
コルーチンの中でコルーチンを実行
ーーー

別のクラスのコルーチンを呼び出す

別のクラスのコルーチンを呼び出すこともできます。クラス.コルーチン名();で呼び出します🐼

StartCoroutine(test2.Hogehoge());

コルーチンの中から別クラスのコルーチンを呼び出すときは、

yield return StartCoroutine(test2.Hogeo());

ーーー

コルーチンの外からコルーチンを停止する

コルーチンの外からコルーチンを停止するときは、メソッドのIEnumeratorを事前に取得しておき、StopCoroutine();に渡すことで止めることができます。

    private IEnumerator coroutine;    

    void Start()
    {
        coroutine = Hogehoge(5, 1.0f);     //先に取得しておく
        StartCoroutine(coroutine);        //この場合コルーチンの実行には変数名を当てる
    }

    void Update(){

        if(Input.GetKeyDown(KeyCode.Return))
        {
            StopCoroutine(coroutine);     //Enterキーが押されたらコルーチンの停止
        }
    }


    private IEnumerator Hogehoge(int num, float wait){

            for(int i = 0; i <= 5; i++){
                text.text = "" + i;
                yield return new WaitForSeconds(wait);
            }
            text.text = "GAME OVER";        
    }

ちなみに、停止なので再開することもできます。
マウスが押されたらStartCoroutine();をする、などすれば、停止と再開が何度でもできます。

全てのコルーチンを止める

ゲーム終了時などに全てのコルーチンを終了したい場合は、

StopAllCoroutines();

で全てのコルーチンを停止させることができます。


以上になります🐼