概要
Unityでゲームを開発していると、「3秒後に敵を出現させたい」「ボタンを押したらフェードアウト処理をしたい」「重いロード処理を数フレームに分けて実行し、フリーズを防ぎたい」といった、時間経過を伴う処理や、一度に実行するとゲームが止まってしまう(フリーズする)ような重い処理を扱いたい場面が頻繁に現れます。
このような処理を通常の関数で実装しようとすると非常に複雑になりますが、Unityにはコルーチン (Coroutine) という、こうした非同期的な処理を非常にシンプルに記述でき る強力な機能が備わっています。この記事では、コルーチンの基本的な仕組みと使い方について、IEnumeratorとyield returnキーワードを中心に詳しく解説していきます。
コルーチンとは?
コルーチンは、処理を一時的に中断し、後で特定のタイミングから再開できる特殊な関数です。通常の関数は一度呼び出されると最後まで実行されなければなりませんが、コルーチンは処理の途中でUnityに制御を一旦戻し、「次のフレームで再開して」「5秒後に再開して」といった指示を出すことができます。
これにより、Update関数を複雑にすることなく、時間ベースのイベントや処理の分割を直感的に実装できます。
コルーチンの基本的な使い方
コルーチンを実装するには、以下の3つの要素が必要です。
IEnumerator型の戻り値を持つ関数: これがコルーチン本体です。IEnumeratorはC#の標準的なインターフェースで、「列挙可能なもの」を意味します。yield return: コルーチンの処理を中断し、Unityに制御を戻すためのキーワードです。この後に再開条件を指定します。StartCoroutine(): 作成したコルーチンを開始するためのメソッドです。
時間を待つコルーチン
最も基本的な使い方は、一定時間待ってから処理を再開するパターンです。yield return new WaitForSeconds(float seconds)を使います。
using System.Collections;
using UnityEngine;
public class CoroutineExample : MonoBehaviour
{
void Start()
{
Debug.Log("コルーチンを開始します。");
// 文字列のメソッド名でコルーチンを開始
StartCoroutine("WaitAndPrint");
}
// IEnumeratorを返す関数としてコルーチンを定義
IEnumerator WaitAndPrint()
{
// 3秒間処理を中断
yield return new WaitForSeconds(3.0f);
// 3秒後にここから処理が再開される
Debug.Log("3秒経過しました!");
}
}
このスクリプトを実行すると、まず「コルーチンを開始します。」と表示され、その3秒後に「3秒経過しました!」と表示されます。Start関数はコルーチンを開始した直後に終了しますが、コルーチンはバックグラウンドで待機を続け、指定した時間が経過すると処理を再開するのです。
yield returnで使える様々な中断条件
yield returnの後には、WaitForSeconds以外にも様々な中断・再開条件を指定できます。
| yield return の後に指定するもの | 再開タイミング |
|---|---|
null | 次のフレームのUpdateが呼ばれる前に再開。 |
new WaitForFixedUpdate() | 次のFixedUpdateの直前に再開。 |
StartCoroutine(AnotherCoroutine()) | AnotherCoroutineが完全に終了した後に再開。コルーチンを入れ子にできる。 |
重い処理を分割する際にはyield return null;がよく使われます。
IEnumerator HeavyProcess()
{
for (int i = 0; i < 10000; i++)
{
// 重い計算処理
DoSomethingHeavy(i);
// 100回ごとに1フレーム待機する
if (i % 100 == 0)
{
Debug.Log(i + "回処理しました。1フレーム休みます。");
yield return null; // ここで処理を中断し、次のフレームで再開
}
}
}
コルーチンの停止
一度開始したコルーチンは、途中で停止することもできます。コルーチンを停止するには、StartCoroutineの戻り値をCoroutine型の変数に保存しておき、StopCoroutineメソッドに渡します。
using System.Collections;
using UnityEngine;
public class StoppableCoroutine : MonoBehaviour
{
private Coroutine myCoroutine;
void Start()
{
Debug.Log("10秒後に何かを実行するコルーチンを開始します。");
myCoroutine = StartCoroutine(LongProcess());
}
void Update()
{
// Cキーが押されたらコルーチンを停止する
if (Input.GetKeyDown(KeyCode.C))
{
if (myCoroutine != null)
{
Debug.Log("コルーチンをキャンセルしました。");
StopCoroutine(myCoroutine);
myCoroutine = null; // 停止後は参照をクリアしておくのが安全
}
}
}
IEnumerator LongProcess()
{
yield return new WaitForSeconds(10f);
Debug.Log("10秒経過!処理を実行しました。");
}
}
StopAllCoroutines()を使えば、そのスクリプトで実行中のすべてのコルーチンを一度に停止することもできます。
まとめ
コルーチンは、Unityにおける非同期処理の基本であり、使いこなせば非常に表現力豊かなロジックをシンプルに記述できます。
- コルーチンは、処理を一時中断・再開できる特殊な関数。
IEnumeratorを戻り値とし、yield returnで処理を中断する。StartCoroutine()で開始し、StopCoroutine()で停止できる。new WaitForSeconds(t)で時間待ち、nullで1フレーム待ちが基本。
時間のかかる演出、AIの思考ルーチン、重い処理の分割など、コルーチンの活躍の場は無限にあります。まずは簡単な時間待ち処理から試してみて、その便利さを体感してみてください。