今回の内容
今回からはシーンの制御の仕組みを作成します。
クリア後に次のステージへ遷移する、ゲームオーバー時にリトライするといった機能を実装していきます。
改めての注意書きとなりますが、ステージ遷移関連の仕組みは実際のゲームで実装している仕組みとは異なっています。
ここで紹介するのは実装方法の1例として見て頂ければと思います。
※初めての方はこちらから
⇒ 【第1回記事】この連載について
シーン制御の設計
いきなりスクリプト作成に入る前に、今回のシーン制御の仕様を簡単に整理します。
「GameScene」+「ステージ番号」
例)GameScene1, GameScene2, …
1周目は順番に選択、2周目以降はランダムとする。
例えば10ステージあるとき、
▼ステージ1-10
GameScene1
GameScene2
GameScene3
…
GameScene10
▼11以降
全シーンの中からランダムで選択
PlayerPrefsを使って管理する。
その際、以下の2つのパラメータを使用。
・StageNum ⇒ 現在何ステージ目かを管理
・SceneNum ⇒ 読み込むシーンの番号を管理(GameScene1の「1」の箇所)
なぜ2つ用意しているかと言うと先ほどの2の仕様関連で、
1周目は「読み込むシーン番号(SceneNum)= 現在のステージ数(StageNum)」となるが、
2周目以降は両者がズレて行くので、別々のパラメータで管理することとしています。
上記3つの仕様を前提として、この後の実装を進めていきます。
シーンを読み込む
新規スクリプトを追加して、名前は「StageControllerScript」としましょう。

まずは以下を記述します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class StageControllerScript : MonoBehaviour
{
public const string GAME_SCENE_NAME = "GameScene"; // シーン名のプレフィクス
public const int GAME_SCENE_COUNT = 1; // シーンの数
private int stageNum; // 現在のステージ数
public Text stageName; // 現在のステージ名("Stage" + stageNum)
void Start()
{
// ステージ数(画面表示用 ※実際のシーン名とは必ずしも対応しない!)
stageNum = PlayerPrefs.GetInt("StageNum", 1);
stageName.text = "Stage" + stageNum;
// 自分のシーンではない場合、ロードし直す
if (GetLoadSceneName() != SceneManager.GetActiveScene().name)
{
LoadScene();
}
}
void Update()
{
}
// ロードするシーン名を取得
private string GetLoadSceneName()
{
int loadSceneNum = PlayerPrefs.GetInt("SceneNum", 1);
return GAME_SCENE_NAME + loadSceneNum;
}
// ステージを読み込む処理(現在のstageNumに対応するステージ)
private void LoadScene()
{
SceneManager.LoadScene(GetLoadSceneName());
}
}
記述ができたら、シーンに空のオブジェクトを配置して名前を「StageController」としましょう。
このオブジェクトに、StageControllerScript をアタッチしてください。

さらにインスペクタービューで、StageName に Canvas > StageName をドラッグして下さい。

この Canvas > StageName って何だったかと言うと、第2回目の記事で作成した、
画面の上部に表示するステージ名のUIでした。

順に解説していきます。
9, 10行目:定数の定義
![]()
それぞれ定数を定義しており、内容はソース内コメントの通りです。
シーンの数は現在は1としていますが、今後ステージを増やしたときにはここを直接変更します。
12, 13行目:プロパティの定義
![]()
こちらは通常のプロパティとして定義しており、内容はやはりコメントの通りです。
StageNum は先ほどの仕様3.の PlayerPrefs と対応するプロパティです。
15~26行目:Startメソッド

はじめに18行目で、現在のステージ数(StageNum)を PlayerPrefs から取得しています。
取得した番号と「Stage」の文字列を結合して、StageName の text プロパティに設定しています。
StageName は画面上部の UI だったので、ここでその表示を設定している形となります。
Startメソッド内の最後にある、22~25行目の処理ですが、
現在のシーンが本来読み込むシーンではない場合に、正しいシーンを読み込み直す処理となっています。
タスクキル等でアプリを終了・再開すると GameScene1 が読み込まれてしまうため、
PlayerPrefs を参照して正しいステージを読み直しています。
34~38行目:GetLoadSceneNameメソッド

その時点で読み込むべきシーン名を取得するメソッドを作成しています。
読み込むシーンの番号は、PlayerPrefs の SceneNum で管理しています。(仕様の3つ目)
この処理は複数の箇所で実行される想定のもと、メソッドとして作成しました。
(現状だと22行目と43行目で使用しています。)
41~44行目:LoadSceneメソッド

シーンを読み込む処理をメソッド化しています。
=====
この後もスクリプトを追記していきますが、まずはここまでの処理を理解してください。
特に大事なことは、以下の2点です。
・LoadSceneメソッドを呼び出すとその時点で読み込むべきシーンが読み込まれる
・読み込むシーンの番号は、PlayerPrefs の SceneNum で管理している
クリア、ゲームオーバーの制御
続いて、クリアやゲームオーバーと言ったゲームの状態を管理するための機能を追加していきます。
まずやることは大きく2つで、
・フラグを追加(クリア、ゲームオーバーそれぞれ)
・フラグの状態によって、UIの表示を切り替える(クリアUI、リトライUIを表示)
ひとまずはここまでを作成します。
StageControllerScript に以下を追加してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class StageControllerScript : MonoBehaviour
{
public const string GAME_SCENE_NAME = "GameScene"; // シーン名のプレフィクス
public const int GAME_SCENE_COUNT = 1; // シーンの数
private int stageNum; // 現在のステージ数
public Text stageName; // 現在のステージ名("Stage" + stageNum)
public static bool isClear; // クリアフラグ
public static bool isGameOver; // ゲームオーバーフラグ
public GameObject clearCanvas; // クリア時のUI
public GameObject retryCanvas; // ゲームオーバー時のUI
void Start()
{
// ステージ数(画面表示用 ※実際のシーン名とは必ずしも対応しない!)
stageNum = PlayerPrefs.GetInt("StageNum", 1);
stageName.text = "Stage" + stageNum;
// 自分のシーンではない場合、ロードし直す
if (GetLoadSceneName() != SceneManager.GetActiveScene().name)
{
LoadScene();
}
// 初期化
isClear = false;
isGameOver = false;
}
void Update()
{
// クリアしたとき
if (isClear)
{
ShowClearCanvas();
enabled = false;
}
// ゲームオーバーのとき
else if (isGameOver)
{
ShowRetryCanvas();
enabled = false;
}
}
// クリアUIを表示する
private void ShowClearCanvas()
{
clearCanvas.SetActive(true);
}
// リトライUIを表示する
private void ShowRetryCanvas()
{
retryCanvas.SetActive(true);
}
// ロードするシーン名を取得
private string GetLoadSceneName()
{
int loadSceneNum = PlayerPrefs.GetInt("SceneNum", 1);
return GAME_SCENE_NAME + loadSceneNum;
}
// ステージを読み込む処理(現在のstageNumに対応するステージ)
private void LoadScene()
{
SceneManager.LoadScene(GetLoadSceneName());
}
}
追記ができたら、インスペクターから
ClearCanvas に Canvas > Clear
RetryCanvas に Canvas > Retry
をそれぞれ設定します。

では追記したスクリプトを見ていきましょう。
ポイントは、「isClear」「isGameOver」の2つのゲーム状態を管理する変数です。
追加した処理、各メソッドはこの2つに関連して動く事となり、
isClear が true ⇒ ShowClearCanvas(クリア時UIが表示される)
isGameOver が true ⇒ ShowRetryCanvas(リトライ時UIが表示される)
となっています。
ここまでできるとシーン制御の完成まであと一歩で、残りの実装としては、
・クリア画面で Nextボタンをタップすると次のシーンを読み込む
・リトライ画面で Retryボタンをタップすると現在のシーンを読み込む
これらの処理を作成するのみとなります。
今回の記事ではこの実装まではせず、次回紹介していくのですが、
実装方法としては先に作成した LoadSceneメソッド や PlayerPrefs の SceneNum を利用します。
宿題がてら、少し実装方法を考えてみて頂くと良さそうです。
デバッグUIの制御
デバッグUIの表示切替も、StageControllerで管理するようにします。
StageControllerScript に以下を追加してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class StageControllerScript : MonoBehaviour
{
public const string GAME_SCENE_NAME = "GameScene"; // シーン名のプレフィクス
public const int GAME_SCENE_COUNT = 1; // シーンの数
private int stageNum; // 現在のステージ数
public Text stageName; // 現在のステージ名("Stage" + stageNum)
public static bool isClear; // クリアフラグ
public static bool isGameOver; // ゲームオーバーフラグ
public GameObject clearCanvas; // クリア時のUI
public GameObject retryCanvas; // ゲームオーバー時のUI
// デバッグ用
private bool isDebug = true; // デバッグフラグ
public GameObject debugCanvas; // デバッグメニューのUI
void Start()
{
// ステージ数(画面表示用 ※実際のシーン名とは必ずしも対応しない!)
stageNum = PlayerPrefs.GetInt("StageNum", 1);
stageName.text = "Stage" + stageNum;
// 自分のシーンではない場合、ロードし直す
if (GetLoadSceneName() != SceneManager.GetActiveScene().name)
{
LoadScene();
}
// 初期化
isClear = false;
isGameOver = false;
// デバッグモード表示の切り替え
debugCanvas.SetActive(isDebug);
}
// 以下省略
クリアやリトライと同様に、DebugCanvasに Canvas > Debug を設定しましょう。

デバッグUI の Retryボタンや Clearボタンをタップした時の処理も次回作成しますが、
実装方法としてはクリア画面やリトライ画面と同様になるので、こちらも宿題がてら考えてみて下さい。
また、まだしばらくはデバッグUI は表示したままとしますので、isDebug の値は true としておきます。(22行目)
おわりに
今回はシーン制御の実装の1回目と言うことで、ボタンを押す手前までの処理を作成しました。
目に見えない箇所の作成だったことと PlayerPrefs等の設計に絡んだ実装がやや難易度が高めかと思いますので、
理解できるまでじっくり読んでみて下さい。
次回は各種ボタンとの関連付けを行って、シーン制御の機能が完成する予定ですのでお楽しみに!
連載目次リンク
関連する連載リンク
© Unity Technologies Japan/UCL