Unityでコルーチンを使って定期的に処理をする

Unityのスクリプトではコルーチンを使う事が出来ます。

コルーチンを使うと一定時間毎に何らかの処理を行う事が出来るようになります。

例えば1分毎に新しい敵を登場させるといった事が出来ます。

Update関数内で時間を計測し時間がきたら敵を登場させる事も出来ますが、コルーチンを使った方が簡単に記述が出来ますし、

Update関数内で時間を毎回計測する処理負荷が軽減されるということもあります。

このコルーチンは通常のスクリプトの流れから外れて動作するのでスクリプトの流れとは別に動作させたい処理がある時に便利です。

ただいわゆるマルチスレッド(複数のスクリプトを並列に動作させる)ではなくシングルスレッドで動いているけど並列して動いているようにみせる事が出来るという事です。

スポンサーリンク

コルーチンの概要

前置きが長くなりましたので、さっそくコルーチンの使い方にいきましょう。

コルーチンを開始する

まずはコルーチンを開始するやり方です。

Test関数が実行する関数です。

↑のように最初のコルーチン開始は通常の関数呼び出しと同じやり方ですがこちらはJavaScriptでしか出来ません。

2番目はStartCoroutineの引数としてTest関数を渡して実行出来ます。

3番目はStartCoroutineの引数としてメソッド名(呼び名が違いますがJavaScriptだと関数名)を渡します。

2番目と3番目は同じようですが実は違いがあります。

3番目のようにメソッド名を渡して実行した場合StopCoroutineを使って動作を止める事が出来ます。

2番目の場合は処理が自然に終了出来るようにするかStartCoroutineの戻り値を変数に保持しておきStopCoroutineを使うか、StopAllCoroutinesが呼ばれるまで止まりません。

コルーチンを停止する

次はコルーチンの停止方法です。

最初のやり方はコルーチンを開始する時に引数にメソッド名を記述した場合に出来る停止方法です。

StartCoroutine(“Test”)

としていた場合だけ

StopCoroutine(“Test”)

が作用します。

それ以外の方法で開始されたコルーチンには適用されず無視されてしまいます。

2番目のStopAllCoroutinesは実行しているコルーチンの関数によらず全てのコルーチンを停止します。

ゲームが終了する時は動作しているコルーチンを全部止めたいと思うので名前を指定せずこちらを呼び出して止めた方が早そうですね。


-- StopCoroutineについての追記(2017/03/17) --

以前StopCoroutineではStartCoroutineの引数に文字列として関数名を渡した時だけ作用すると書きましたが、StartCoroutineの戻り値はCoroutine型であり、

スタートさせたコルーチンの参照を保持しておくことも出来るようです。

つまり

とStartCoroutineでスタートさせたコルーチンの参照変数を保持しておき、StopCoroutineでその参照変数を使ってコルーチンを止める事が出来ます。

指摘されるまで全然気が付きませんでした。m(__)m

なお今回のサンプルでは連続してコルーチンを開始させているので開始させる毎に別の参照変数へと入れていかないといけません。

-- StopCoroutineについての追記終了 --

コルーチンの戻り値

さて、一番わかり辛いと思うのがコルーチンの戻り値です。

戻り値がIEnumerator型という事でチンプンカンプンです・・・・(-_-)

ここが特殊で解り辛いところですね・・・、やり方だけ覚えてしまいましょう。

さきほどから登場していた実行しているコルーチンTest関数を見ていきます。

JavaScriptとC#では記述が少し変わるので両方を載せておきます。

まずはJavaScriptでの記述を見てみましょう。

JavaScriptでは通常の関数と同じ記述で戻り値を記述しなくて大丈夫です。

明示的に

function Test() : IEnumerator {

としても大丈夫です。

yieldという見慣れない記述がありますが、難しい事はわかりません・・・・(^_^;)

一旦次のフレームに飛ばすと考えてもらえばいいのかもしれません。

yield WaitForSeconds(1.0f)

と記述すると1秒後に次のフレームに飛ばします。

yield

だけだとその場で次のフレームに飛ばします。

次はC#での記述を見てみましょう。

C#で1秒待つには

yield return new WaitForSeconds(1.0f)

と記述します。

次のフレームに飛ばすには

yield return null

です。

JavaScriptとC#では多少記述が変わっていますね。

コルーチンのサンプルを作成する

コルーチンの概要を見てもよくわからないと思うので実際にサンプルを作って実行してみましょう。

以下のスクリプトを作成しMainCamera等のゲームオブジェクトに取りつけます。

ヒエラルキー上で右クリック→UI→Textを作成し、このスクリプトのインスペクタにこのTextを設定します。

Spaceキーを押すとコルーチンをスタートさせます。

今回は引数にメソッド名を記述するやり方でやります(他のはコメント化してあります)。

1キーを押すと動作しているコルーチンを全部停止させます。

その為Test関数以外のコルーチンTester関数を作り実行していたとしても停止します。

Testだけを停止するには

StopCoroutine(“Test”)

を使います。

実際に動作しているTest関数内を見ていきましょう。

Test内ではローカル変数であるcountを宣言し0で初期化しています。

whileループで常に条件がtrueなので繰り返し実行します。

その中でcountの値を表示しカウントアップ、yield WaitForSeconds(1.0f)で1秒待機したあとyieldで次のフレームに飛ばします。

その為1秒毎にcountの数字を永遠表示し続ける処理になります。

count変数は毎回0に初期化されるような気がしますが、実際はカウントアップされていきます。

次のフレームに移動してもwhileループの中にいると考えるといいのかも?

このサンプルではSpaceキーを押すたびにコルーチンを開始していますが、そうするとどうなるのでしょうか?

実は新しくコルーチンが開始され、前に開始したコルーチンとは別物が動作します。

その為Spaceキーを押すたびに新しいコルーチンが開始されコンソールにそれぞれのカウントがされていくことになります。

次はC#で記述したスクリプトです。

書いてある事は同じです。

それではサンプルを実行してみましょう。

コルーチン実行サンプル

何秒かおきにSpaceキーを押してコルーチンを開始しています。

コンソールに違うコルーチンのカウントが表示されていってますね。

途中で1キーを押してコルーチンを全て停止し、コンソールのClearボタンを押してコンソールを消しコルーチンが停止している事を確認しています。

その後再びSpaceキーを押して新しいコルーチンを開始してます。

コルーチンを使ってみて

正直なところコルーチンは使い方がわかり辛いので全然使ってなかったんですが、場合によっては非常に便利かもしれませんね。

Update関数内で何らかの条件に合致するか判定する場合1秒間に何十回も判定をしてしまいますが、もっと少ない回数で条件を判定したい時は

コルーチンを使って自分で指定した秒数毎に条件を判定するようにすれば判定回数が減って処理速度の向上に繋がる可能性があります。

でもIEnumerator型やらyieldやら使い方がわかり辛いですね・・・・(^_^;)

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます

コメント

  1. しろくろ より:

    StartCoroutine(Test());の書き方でも途中で止めれますよー

    Coroutine coroutine = StartCoroutine(Test());
    StopCoroutine(coroutine);

    これで止められます。

    Coroutine coroutineA = StartCoroutine(Test());
    Coroutine coroutineB = StartCoroutine(Test());
    StopCoroutine(coroutineA);

    といった風に、同じコルーチンを走らせて片方だけ止めるとかもできます。

    関数名指定のコルーチンと違って、インスタンスとしてコルーチン管理したい人向けですね。