概要
ゲームは通常、単一のシーンで完結するものではありません。「タイトル画面」でスタートボタンを押すと「ゲーム本編」のシーンに移動し、ゲームオーバーになったら「リザルト画面」のシーンに移動する、といったように、複数のシーンを遷移することでゲームの流れが作られます。
Unityでは、このシーン間の移動を管理するための専用のクラスとして SceneManager が用意されています。この記事では、SceneManagerクラスを使った基本的なシーンのロード方法から、ロード画面を実装するための非同期 ロードまで、シーン遷移に関する必須知識を解説します。
シーンをビルド設定に追加する
スクリプトからシーンをロードする前に、まず対象となるすべてのシーンをビルド設定に登録しておく必要があります。これを忘れると、エディタ上では動作しても、実際にゲームをビルドした際にシーンが見つからずエラーになってしまいます。
File > Build Settings...を選択してビルド設定ウィンドウを開きます。Scenes In Buildというリストが表示されます。- プロジェクトウィンドウから、ゲームで使用するすべてのシーンファイル(
.unity)をこのリストにドラッグ&ドロップします。
リストに追加されたシーンには、0, 1, 2... というビルドインデックスが割り振られます。このインデックス番号、またはシーンファイル名(拡張子なし)を使って、スクリプトからシーンをロードすることができます。
ポイント: 一般的に、ビルドインデックス0はゲームの起動時に最初に読み込まれるシーン(タイトル画面やスプラッシュスクリーンなど)に設定します。
基本的なシーンロード: LoadScene()
シーンをロードする最も簡単な方法は、SceneManager.LoadScene()メソッドを使うことです。このメソッドを使うには、スクリプトの先頭にusing UnityEngine.SceneManagement;を追加するのを忘れないでください。
LoadScene()は同期的に動作します。つまり、このメソッドが呼ばれると、現在のシーンの破棄と新しいシーンの読み込みが完了するまで、ゲームの実行が完全に停止します。ロードに時間がかかる重いシーンの場合、ゲームが一瞬フリーズしたように見えることがあります。
シーン名でロードする
using UnityEngine;
using UnityEngine.SceneManagement; // これが必要!
public class TitleScreen : MonoBehaviour
{
public void OnStartButtonClick()
{
// ビルド設定に追加したシーンのファイル名を文字列で指定
SceneManager.LoadScene("GameStage1");
}
}
ビルドインデックスでロードする
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameController : MonoBehaviour
{
public void GoToTitle()
{
// ビルドインデックス0番のシーン(タイトル画面)をロード
SceneManager.LoadScene(0);
}
}
非同期ロードとロード画面の実装: LoadSceneAsync()
ゲームがフリーズするのを避け、ロード中であることをプレイヤーに伝える「ロード画面」を実装するには、非同期でのシーンロードが必要です。SceneManager.LoadSceneAsync()メソッドは、バックグラウンドでシーンの読み込みを行い、その間もゲームの実行を止めません。
LoadSceneAsync()は、ロード処理の状況を管 理するAsyncOperationオブジェクトを返します。このオブジェクトのプロパティを調べることで、ロードの進捗状況を取得したり、ロードが完了したかを検知したりできます。
以下は、簡単なロード画面の実装例です。
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI; // UI要素を操作するために必要
public class LoadingScreen : MonoBehaviour
{
public Slider progressBar; // ロードの進捗を表示するUIスライダー
public Text progressText; // 進捗をパーセント表示するUIテキスト
public void LoadScene(string sceneName)
{
// コルーチンを開始して非同期ロードを行う
StartCoroutine(LoadAsynchronously(sceneName));
}
IEnumerator LoadAsynchronously(string sceneName)
{
// LoadSceneAsyncメソッドでシーンを非同期でロード開始
AsyncOperation operation = SceneManager.LoadSceneAsync(sceneName);
// isDoneがtrueになるまでループ
while (!operation.isDone)
{
// progressは0.0から0.9までの値をとる(0.9でロード完了扱い)
float progress = Mathf.Clamp01(operation.progress / 0.9f);
// プログレスバーとテキストを更新
progressBar.value = progress;
progressText.text = (progress * 100f).ToString("F0") + "%";
// 1フレーム待つ
yield return null;
}
}
}
operation.progressは、ロードが90%完了した時点で0.9という値を返します。実際のシーンのアクティベーション(表示の切り替え)は最後の10%で行われるため、100%表示にするにはprogress / 0.9fのように計算するのが一般的です。
まとめ
シーン遷移は、ゲームの構造を定義する上で不可欠な機能です。
SceneManagerクラスを使ってシーンを遷移する。- ロードしたいシーンは、必ずビルド設定に追加しておく。
LoadScene(): シンプルな同期ロード。ロード中はゲームが停止する。LoadSceneAsync(): 高度な非同期ロード。ロード画面の実装に必須。
プレイヤーを待たせている間も、プログレスバーを表示したり、ゲームのヒントを表示したりすることで、待ち時間のストレスを軽減できます。ユーザー体験を向上させるためにも、LoadSceneAsyncを使いこなせるようになりましょう。