今回はUnity初心者の方向けの話題で、
を丁寧に解説するという内容になっています。
Unityでゲームを作っていると「〇秒間だけ待ってから処理を実行したい」という場面がよくあると思うのですが、そんな時にはコルーチンがとても役に立ちます。ただ初心者の方の中には「げ~っ、コルーチンかよ!」「コルーチンってなんか使い方がよく分かんないんだよね…」と思ってしまう方も少なくないのではないでしょうか。
そこでこの記事ではコルーチンの使い方をサンプルスクリプトも交えて詳しくご説明しますね。
そもそもコルーチンとは?
まずはじめに、そもそもコルーチンって何だよと思う方もいらっしゃるかもしれませんので簡単に説明しておきます。
コルーチンは一言でいえば「処理を途中で止めることができる特殊な関数」です。普通の関数は原則として1フレームの間に最初から最後まですべての処理が行われるのですが、コルーチンの場合は処理を途中で止めて別のフレームでまた再開することができるのです。つまり複数のフレームにまたがって処理を行えるのがコルーチンだともいえるでしょう。
このような性質を持つコルーチンを使えば「〇秒後に処理を実行する」といったことを簡単に実現することができます。例えば次のような処理に応用することが可能です。
- プレイヤーが銃の発射ボタンを押している間、一定間隔で弾が発射されるようにする
- 爆弾が出現後一定時間すると爆発する
- 必殺技を使った後のクールダウンを設定する
コルーチンの具体的な使い方
ではここからコルーチンの使い方を具体的に説明していきます。
コルーチンの定義
まずはコルーチンの定義のやり方についてです。次のサンプルスクリプトをご覧ください。
using System.Collections; using UnityEngine; public class CoroutineSample : MonoBehaviour { void Start() { StartCoroutine("TestCoroutine"); } IEnumerator TestCoroutine() { Debug.Log("コルーチンを開始します。3秒待ちます。"); yield return new WaitForSeconds(3); Debug.Log("3秒待ちました。"); } }
「TestCoroutine」がコルーチンの本体です。コルーチンの使い方で一番注目していただきたいのが「yield return ~」の部分で、例えばここに「new WaitForSeconds(3)」と書くと3秒間処理を待つことができます(=3秒後に続きの処理を実行します)。
ちなみに待ち時間はWaitForSeconds関数の他にも
- yield return null:1フレームだけ待つ
- yield return new WaitForEndOfFrame():そのフレームが終わるまで待つ
などの指定が可能です。
その他、コルーチンの場合は一般的な関数とは違って
- 冒頭に「using System.Collections」が必要
- yield returnは必ず一か所以上に書く必要がある
- 戻り値の型として「IEnumerator」を指定する必要がある
といった点に注意してください。これ以外は他の関数の書き方と大体同じで、上のサンプルでは引数なしですが引数付きのコルーチンを定義することもできます。
開始
お次はコルーチンを開始させる方法については「StartCoroutine」関数を使います。先ほどのサンプルスクリプトの場合であれば、Start関数内に書いてある通り
StartCoroutine("TestCoroutine");
と書けばOKです。ただし文字列で指定すると、Visual Studio等で関数をどこから参照しているかを追うのが難しくなってしまいますので、個人的には下の書き方がオススメです。
StartCoroutine(nameof(TestCoroutine));
また、他にも次のような書き方ができます。引数付きのコルーチンの場合はこちらを使ってください。
StartCoroutine(TestCoroutine());
ちなみに中級者向けのテクニックになりますが、コルーチンはIEnumerator型の変数にキャッシュしておくことができます。
IEnumerator routine; void Start() { routine = TestCoroutine(); StartCoroutine(routine); }
こうすると、後述するコルーチンの再開処理を作ることができます。
停止
開始したコルーチンを停止させるには「StopCoroutine」関数を使います。使い方はStartCoroutine関数と同じです。次のサンプルスクリプトをご覧ください。
using System.Collections; using UnityEngine; public class CoroutineSample : MonoBehaviour { bool isStopped = false; void Start() { StartCoroutine(nameof(TestCoroutine)); } void Update() { if (Input.GetKeyDown(KeyCode.Space)) { if (!isStopped) { StopCoroutine(nameof(TestCoroutine)); isStopped = true; } else { StartCoroutine(nameof(TestCoroutine)); isStopped = false; } } } IEnumerator TestCoroutine() { int count = 0; while (true) { count++; Debug.Log(count); yield return new WaitForSeconds(1); } } }
1秒ごとに秒数をカウントしたログを出すコルーチンです。Spaceキーを一度押すことでカウントを停止し、もう一度Spaceキーを押すと最初からカウントし直す処理となっています。
このようにStopCoroutineを使うことでコルーチンの停止ができるのですが、開始時と同じ引数を指定しないと正常に停止しないのでご注意ください。つまり上のサンプルであれば「StartCoroutine(nameof(TestCoroutine))」となっているので、停止時も同様に「StopCoroutine(nameof(TestCoroutine))」にしないとダメということです。
再開
さて、先ほどのサンプルではコルーチンを停止するとカウントがリセットされてしまうのですが、場合によってはそのままカウントし続けたいときもあります。その場合はコルーチンを変数にキャッシュしておき、それを指定することで続きから再開することができます。
using System.Collections; using UnityEngine; public class CoroutineSample : MonoBehaviour { bool isStopped = false; IEnumerator routine; void Start() { routine = TestCoroutine(); StartCoroutine(routine); } void Update() { if (Input.GetKeyDown(KeyCode.Space)) { if (!isStopped) { StopCoroutine(routine); isStopped = true; } else { StartCoroutine(routine); isStopped = false; } } } IEnumerator TestCoroutine() { int count = 0; while (true) { count++; Debug.Log(count); yield return new WaitForSeconds(1); } } }
中断
コルーチンの処理を途中で中断したい場合は「yield break」を使えばOKです。
IEnumerator TestCoroutine2() { yield return new WaitForSeconds(1); // ここで中断 yield break; }
おまけ:WaitForSecondsはキャッシュできる
最後に余談ですが、WaitForSecondsは変数にキャッシュすることができます。
IEnumerator TestCoroutine() { int count = 0; WaitForSeconds wait = new WaitForSeconds(1); while (true) { count++; Debug.Log(count); yield return wait; } }
実はWaitForSecondsを頻繁にnewするとメモリにゴミが溜まってゲームが重くなる場合があるのですが、このようにキャッシュしておけばそのような心配はありません。なので予め待ち時間が分かっている場合はキャッシュしておくとよいでしょう。
おわりに
以上、コルーチンの使い方を丁寧に解説しました。
コルーチンは一見すると取っつきづらい印象があるかもしれませんが、使いこなせるようになればゲーム開発が格段に楽になり、さらに色々な処理を実現できるようになるのでとても便利です。ぜひ上記の内容を参考にして使い方をマスターしていただければと思います。
この記事がUnityでのゲーム開発のお役に立てば幸いです。