ボタンを押すと引数として指定した時間とメッセージが、コルーチンが再開、停止する。
Unityのコルーチン(Coroutine)はゲーム開発において非同期処理を実現するための強力なツールです。
本記事では、コルーチンの停止や再開についてわかりやすく解説します。
Unityでスムーズにタイマー処理やループ処理をしたい方に特におすすめです。
また、指定した時間後に処理を行う方法として、
「Invoke」メソッドやAwaitがあります。
コルーチンとの違いにも触れて紹介します。
- コルーチンを使ったUnityでの開発に挑戦したい人
- コルーチンの停止と再開の方法を知りたい人
- 非同期処理を使ってスムーズなゲーム体験を実現したい人
- Unityの基本機能からステップアップを考えている人
- ゲームの演出やタイマーを工夫したい人
- Invoke、Awaitとの違いを知りたい。
コルーチン(Coroutine)
コルーチンは、複数のフレームにまたがって実行されるタスクを扱うための方法です。
Unityだけではなく、他のプログラミング言語でも用いられる概念です。
複数フレームにわたる処理や、一定間隔で繰り返し実行する処理に適しています。
また、yield returnを使用して、任意のタイミングで一時停止や再開ができます。
Invokeよりもコード数が多くなりますが、複雑な処理ができることを示しています。
yield return null
コルーチンの実行を次のフレームまで一時停止します。
Start FrameとNext Frameのログ出力は異なるフレームで行われます。
この特性を活用することで、よりダイナミックなゲームの挙動を実現できます。
例えば、プレイヤーの操作に応じてコルーチンを一時停止し、
再開することで、ゲーム内の特定の処理をコントロールできます。
using UnityEngine;
using System.Collections;
public class Sample1 : MonoBehaviour
{
void Start()
{
StartCoroutine(Sample1Coroutine());
}
IEnumerator Sample1Coroutine()
{
Debug.Log("Start Frame: " + Time.frameCount);
// 次のフレームまで待機
yield return null;
Debug.Log("Next Frame: " + Time.frameCount);
}
}
yield return new WaitForSeconds(seconds)
指定した秒数だけ待機するために使用します。
Invokeに似ている処理をします。
Before WaitとAfter Waitの間に2秒の待機時間が存在します。
using UnityEngine;
using System.Collections;
public class Sample2 : MonoBehaviour
{
void Start()
{
StartCoroutine(Sample2Coroutine());
}
IEnumerator Sample2Coroutine()
{
Debug.Log("Before Wait: " + Time.time);
// 2秒待機
yield return new WaitForSeconds(2f);
Debug.Log("After Wait: " + Time.time);
}
}
yield return new WaitUntil(() => condition)
指定した条件が満たされるまで待機するために使用します。
Sample3のCoroutineはisConditionMetがtrueになるまで待機します。
ChangeConditionAfterDelayコルーチンが3秒後に条件を変更します。
using UnityEngine;
using System.Collections;
public class Sample3 : MonoBehaviour
{
private bool isConditionMet = false;
void Start()
{
StartCoroutine(Sample3Coroutine());
StartCoroutine(ChangeConditionAfterDelay());
}
IEnumerator Sample3Coroutine()
{
Debug.Log("Waiting for condition to be met...");
// 条件が満たされるまで待機
yield return new WaitUntil(() => isConditionMet);
Debug.Log("Condition met!");
}
IEnumerator ChangeConditionAfterDelay()
{
// 3秒待機
yield return new WaitForSeconds(3f);
isConditionMet = true;
Debug.Log("Condition changed!");
}
}
戻り値の取得
コルーチンは戻り値を直接返すことはできませんが、IEnumeratorとyield returnを組み合わせて、複数のフレームに渡る非同期処理を管理できます。
UnityではUnityWebRequestなどでサーバーからのデータを非同期で受け取るのにコルーチンを利用することがあります。
IEnumerator FetchData()
{
UnityWebRequest request = UnityWebRequest.Get("https://example.com/data");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
Debug.Log("Data: " + request.downloadHandler.text);
}
else
{
Debug.LogError("Failed to fetch data");
}
}
コルーチンの注意点
コルーチンを利用する際にはいくつか注意が必要です。
コルーチンはStopCoroutine()を呼び出さない限り、
ループが続き、メモリやCPUのリソースを消費します。
そのため、必要なくなったコルーチンは必ず停止するようにしましょう。
また、似たような非同期処理としてInvokeやasync/awaitもあるため、
それぞれの用途を理解して使い分けることが重要です。
Invoke
Invokeは、Unityで特定の時間が経過した後にメソッドを一度だけ実行するシンプルな方法です。
Invoke("メソッド名", 遅延時間)
一例として、MessageFnメソッドを実行するようにします。
5秒後にConsoleウィンドウにテキストを表示します。
using UnityEngine;
public class Invoke_Example : MonoBehaviour
{
void Start()
{
// 5秒後にMessageFnメソッドを呼び出す
Invoke("MessageFn", 5f);
}
void MessageFn()
{
Debug.Log("5秒経過しました");
}
}
Invokeは他にも繰り返しの処理InvokeRepeating、
Invokeの処理を停止するCancelInvokeなどがあります。
操作も簡単ですが、複雑な処理には不向きです。
Await
C#のasync/awaitは非同期メソッドの実行を簡単にするものです。
Unityでは2020年以降のバージョンでTaskを使った非同期処理が可能となっており、Web API呼び出しや非同期ファイルI/Oに便利です。
private async void Start()
{
await Task.Delay(2000);
Debug.Log("Task Complete");
}
引数があるコルーチン
コルーチンは引数を受け取ることが可能で、これにより柔軟な処理を行えます。
例えば、何秒待つかを引数として受け取ることで、
同じコルーチンを複数の場面で使いまわすことができます。
ソースコード
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class CoroutineTest : MonoBehaviour
{
public Button button;
private Coroutine routine; // コルーチンの参照を保持
void Start()
{
// ボタンのクリックイベント
button.onClick.AddListener(ToggleCoroutine);
}
// コルーチンの開始と停止を切り替える
void ToggleCoroutine()
{
if (routine == null)
{
// コルーチンが動いていない場合は開始
routine = StartCoroutine(DisplayMessage("Hello, Unity!", 1));
}
else
{
StopCoroutine(routine);
routine = null;
Debug.Log("コルーチンを停止しました");
}
}
// 1秒ごとにメッセージを表示するコルーチン
IEnumerator DisplayMessage(string message, float interval)
{
while (true)
{
Debug.Log(message);
yield return new WaitForSeconds(interval); // 指定された秒数待機
}
}
}
UdemyでUnityを学習
Udemyは、オンデマンド式の学習講座です。
趣味から実務まで使えるおすすめの講座を紹介します。
- 【Unity C# ゲーム開発超入門】7つのミニゲームを作っておぼえる!UnityとC#講座
Unityで頻出の機能を実際のゲーム作りで学習。
何か作りたい、今後の開発で役立てたい初心者におすすめ
- 【Unity C# ゲーム開発初心者レベルアップ】7つのトランプゲームを作っておぼえる!UnityとC#講座
トランプやボードゲーム作りに特化している講座。
テーブルゲームを作りたい人におすすめ。
- 【全行程を網羅!最初に学びたい総合学習】Unityワールド制作講座
Unityワールド制作の全工程を学習できる講座。
RPGを作りたい人におすすめ。
- Unity ゲーム開発:インディーゲームクリエイターが教える C#の基礎からゲームリリースまで【スタジオしまづ】
C#の文法やApp StoreとGoogle Playへゲームをリリース方法を解説。
ゲームを出品したい人におすすめ。
解説
- 名前空間
「System.Collections」:コルーチンを使うために必要な名前空間。IEnumeratorを利用することで、コルーチンとして処理を記述できます。
「UnityEngine」:Unityの基本機能を利用するための名前空間。MonoBehaviourクラスやDebugクラスなどのUnityのコア機能が含まれています。
「UnityEngine.UI」:UI関連のクラスを利用するための名前空間。ButtonなどのUIコンポーネントを操作するために必要です。
- フィールド(メンバ変数)
「button」:Inspectorでボタンをアタッチするための変数。ユーザーがクリックするボタンを割り当てることができます。
「routine」:コルーチンの参照を保持するための変数。コルーチンを開始・停止する際に使用され、実行中のコルーチンを追跡するために利用されます。
- Startメソッド
ゲーム開始時に呼び出される初期化メソッド。buttonに対してクリックイベントとしてToggleCoroutineメソッドを登録しています。このメソッドにより、ボタンをクリックするたびにToggleCoroutineが呼び出されるようになります。
- ToggleCoroutineメソッド
コルーチンの開始と停止を切り替える処理を行います。routineがnullの場合、コルーチンが動いていないことを意味し、新しいコルーチンDisplayMessageを開始します。すでにroutineが存在する場合は、実行中のコルーチンを停止し、routineをnullにして参照を解放します。
- DisplayMessageメソッド
指定されたメッセージを指定された間隔(interval)で表示するコルーチンです。無限ループを用いてDebug.Logでメッセージを表示し、毎回yield return new WaitForSeconds(interval)で指定された時間待機します。この処理により、1秒ごとに継続的にメッセージをログに出力します。
実演
ボタンをクリックすることでコルーチンが開始され、
指定したメッセージが1秒ごとにログに出力されます。
ボタンを再度クリックすることでコルーチンが停止し、
次のボタンのクリックまでメッセージの出力が中断されます。
このように、ユーザー操作に応じてコルーチンを動的に制御することが可能です。
まとめ
この記事では、Unityのコルーチンを使って非同期処理の停止や再開について解説しました。
コルーチンは非常に便利ですが、適切に管理しないとパフォーマンスに悪影響を与えることもあります。
Invokeやasync/awaitとの違いを理解し、適材適所で使い分けましょう。