Help us understand the problem. What is going on with this article?

Unityにおけるコルーチンの性質まとめ

More than 5 years have passed since last update.

コルーチンとは?

コルーチンとはプログラミングの構造の一種。コルーチンの特徴は処理の途中で一旦中断したりあとからその行から再開できたりすることだ。C#では以下の様な実装の仕方をする。

コルーチンの実装の例

コルーチンは以下のような宣言をします。

IEnumerator coRoutine(){
    msgText.text += "1 ";
    yield return null;
    msgText.text += "2 ";
    yield return null;
    msgText.text += "3 ";
}

IEnumeratorはコルーチンのインターフェースという意味です。とりあえずコルーチンを作るには型をIEnumeratorにすれば作れるということです。(この表現正確にはおかしいんだけどね。)yield return null はココで処理を中断するということです。Unityでは、1フレーム分中断して、次のフレームで続きの行の処理を行います。つまりココでは"1 "を出力したら1フレーム待って"2 "を出力し、さらに1フレーム待って"3 "を出力します。

コルーチンを使う(Unity only)

//例えばStart()関数で使いたい時
void Start(){
    StartCoroutine("coRoutine");
}

コルーチンは「coRoutine();」という書き方をしても動きません。そもそもこいつはインターフェースだしね。コルーチンを動かしたいときは、StartCoroutine()を使います。StartCoroutine("coRoutine")は「"coRoutine"というコルーチンを開始する」という意味の関数です。まんまですね。

この場合出力結果は以下のようになります。

1 2 3

あれ? yield return null 働いてなくね?」って思った方。ちゃんと働いています。ではStart()関数を以下のように変更してみてください。

//例えばStart()関数で使いたい時
void Start(){
    StartCoroutine("coRoutine");
    StartCoroutine("coRoutine");
}

出力結果はこうです。

1 1 2 2 3 3

もし yield return null が働いていないなら出力は

1 2 3 1 2 3

となるはずですよね。どういうことかというと、まず最初のStartCoroutineが始まって"1 "を出力します。その後 yield return null で"coRoutine"の処理は中断されます。次のStartCoroutineでまた"1 "が出力されて、同じように yield return null で"coRoutine"の処理は中断されます。そこでStart()関数は終了しますが、1フレーム待って2つの"coRoutine"が再開されるので"2 ","2 "と数字が出力されるわけです。それが3まで繰り返され、コルーチンが終了します。

コルーチンの処理の中断と再開のメカニズムが分かったでしょうか?

コルーチンの中断・終了の仕方いろいろ

yield return null;

1フレーム処理を中断し、再開します。

yield return new WaitForSeconds( num );

num秒間の間処理を中断します。

yield break;

コルーチンを途中で終了します。中断ではないので再開はされません。

Update()内でStartCoroutine()を使うときの注意

Update()内でStartCoroutine()を使うときは注意が必要です。Update()は毎フレームごとに処理される関数なので、スタートさせるコルーチンが1フレームで終了しない場合だと、毎フレームごとにどんどん増えていきます。コルーチンの唯一性を保ちたい場合は以下のように記述します。

bool isRunning = false;

IEnumerator coRoutine(){
    if (isRunning)
        yield break;
    isRunning = true;

    msgText.text += "1 ";
    yield return null;
    msgText.text += "2 ";
    yield return null;
    msgText.text += "3 ";

    isRunning = false;
}

isRunningでコルーチンの動作状態を保持し、動いている場合はyield breakして、余計なコルーチンが作られるのを阻止します。

kazz4423
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした