Skip to main content

Unityで待機ができる処理:非同期処理

概念

Unityのスクリプトでは、Start()Update()OnTriggerEnter() などの定めたときに実行するメソッドがある(初期の時、フレーム毎、トリガーに入った)

この機能が大変便利であるが、ゲームを開発中には、上記のメソッドを呼び出される瞬間ではなく、少し時間たってから実行したい場合もたくさんある。

例えば:

  • 体力がゼロになった場合、すぐにゲームオーバーを表示するのではなく、主人公が倒れるアニメーションを再生し終わってからゲームオーバーを表示したい。
  • ローディング画面を表示し、次のステージの準備ができてからシーンを切り替える。
  • サイコロをランダムに回し、プレーヤーを「停止」を押してからすごろくのコマを進む。

この場合は「待機」が発生する。何かの条件を満たすまで待たないといけない。Unityでは2つの作戦がある:コルーチン と Awaitable.

コルーチン

コルーチンの書き方は以下の通りである

 

private IEnumerator コルーチン名 (引数)
{
  // 処理
  // yield return 待機命令
  // 処理
  // yield return 待機命令
  // ...
}

普通のメソッドとよく似ているが、戻り値は必ず IEnumerator になる。そして、中には普通の処理を行い、待機命令を見つけたらコルーチンが一時停止し、待機が終わったら再開する流れになる。

なお、コルーチンを開始するのは、普通のメソッドとして呼び出すことではなく、以下の通りになる:

StartCoroutine(コルーチン名(引数));

また、待機命令は以下から選択ができる

命令 効果

yield return null;

次のフレームまで待つ
yield return new WaitForSeconds(秒数); 定めた秒数を待機する
yield return StartCoroutine(他のコルーチン); 別のコルーチンが終わるまで待機する

この他にもいくつかの待機命令があるが、最も多く使うのは上記に3つである。

例:READY → GO!

あるゲーム開始の時に、「READY」を2秒を表示した後、「GO!」を表示1秒表示し、その後ゲームを開始ができる処理を実装しようとしたら:

// ゲーム開始
public void StartGame()
{
	// コルーチンを開始
	StartCoroutine(ReadyGo());
}

// レディー → ゴー!を表示するコルーチン
private IEnumerator ReadyGo()
{
	// READY を表示
	Debug.Log("READY");
	
	// 2秒待機
	yield return new WaitForSeconds(2.0f);
	
	// GO! を表示
	Debug.Log("GO!");
	
	// 1秒待機
	yield return new WaitForSeconds(1.0f);

	// 実際にゲームを開始
	Debug.Log("ゲーム開始");
}

Awaitable

Awaitable(アウェイタブル)は改善されたコルーチンといわれる。基本的に同じことするのが、書き方が少し難しくなる。

private async Awaitable 非同期処理 (引数)
{
  // 処理
  // await 待機命令
  // 処理
  // await 待機命令
  // ...
}

そして、開始するのは、普通のメソッドと同じである

非同期処理 (引数);

また、待機命令は以下の通りになる:

命令 効果

await Awaitable.NextFrameAsync();

次のフレームまで待つ
await Awaitable.WaitForSecondsAsync(秒数); 定めた秒数を待機する
await 他の非同期処理(引数); 別のAwaitableが終わるまで待機する

例:READY → GO!

コルーチンで作った処理をAwaitableにすると:

// ゲーム開始
public void StartGame()
{
	// 処理開始
	ReadyGo();
}

// レディー → ゴー!を表示する非同期メソッド
private async Awaitable ReadyGo()
{
	// READY を表示
	Debug.Log("READY");
	
	// 2秒待機
	await Awaitable.WaitForSecondsAsync(2.0f);
	
	// GO! を表示
	Debug.Log("GO!");
	
	// 1秒待機
	await Awaitable.WaitForSecondsAsync(1.0f);

	// 実際にゲームを開始
	Debug.Log("ゲーム開始");
}