
【Unityゲーム開発】画面切り替えのススメ
概要
ゲーム開発にはゲーム画面、設定画面などたくさんの画面が必要になります。下の画像はシューティングゲームの例なのでシンプルですが、もっとUIを駆使するRPGのようなゲームだと作っているうちに複雑になり、整理しきれなくて苦労した経験のある人も多いのではないでしょうか。自分なりの解決方法について解説します。

失敗例
例えばあるゲームに次の3種類の画面があったとします。
①タイトル画面
②設定画面
③ゲーム画面
これらの画面を切り替えるためにこんな感じのスクリプトを書くことが考えられます。画面の切り替えというのは基本的にゲームオブジェクトの表示・非表示で行います。
public GameObject ui_Title;
public GameObject ui_Config;
public GameObject ui_Game;
public void OpenUI(int num)
{
if (num == 1) //タイトル画面
{
ui_Title.SetActive(true);
ui_Config.SetActive(false);
ui_Game.SetActive(false);
}
else if (num == 2) //設定画面
{
ui_Title.SetActive(false);
ui_Config.SetActive(true);
ui_Game.SetActive(false);
}
else if (num == 3) //ゲーム画面
{
ui_Title.SetActive(false);
ui_Config.SetActive(false);
ui_Game.SetActive(true);
}
}
各画面ごとにSetActiveで表示・非表示切り替えをして目的の画面だけを表示させています。画面がこの3つだけならこれでもいいですが、ここに例えば「ランキング画面」を新しく追加した場合、次のようになります。
public GameObject ui_Title;
public GameObject ui_Config;
public GameObject ui_Game;
public GameObject ui_Ranking;
public void OpenUI(int num)
{
if (num == 1) //タイトル画面
{
ui_Title.SetActive(true);
ui_Config.SetActive(false);
ui_Game.SetActive(false);
ui_Ranking.SetActive(false);
}
else if (num == 2) //設定画面
{
ui_Title.SetActive(false);
ui_Config.SetActive(true);
ui_Game.SetActive(false);
ui_Ranking.SetActive(false);
}
else if (num == 3) //ゲーム画面
{
ui_Title.SetActive(false);
ui_Config.SetActive(false);
ui_Game.SetActive(true);
ui_Ranking.SetActive(false);
}
else if (num == 4) //ランキング画面
{
ui_Title.SetActive(false);
ui_Config.SetActive(false);
ui_Game.SetActive(false);
ui_Ranking.SetActive(true);
}
}
分岐が1つ増える上に、各分岐ごとの表示・非表示切り替えも1つずつ増えます。もちろんゲーム中に使う画面の数はこんなものではないので、この調子でスクリプトを書いていくと恐ろしいことになるので良くありません。
解決方法
自作クラス作成
次のようなスクリプトを作ると、どんなに画面が増えても煩雑にならずに簡単に対応できます。
ActivationManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ActivationManager : MonoBehaviour
{
public List<GameObject> targetList;
//対象のオブジェクトのみ表示し、対象以外のオブジェクトは非表示にする
public void Activate(int num)
{
for (int i = 0; i < targetList.Count; i++)
{
targetList[i].SetActive(i == num);
}
}
}
targetListに登録されている複数のゲームオブジェクトのうち、対象とするゲームオブジェクトのみ表示し、それ以外のゲームオブジェクトは全て非表示にする、という処理を行います。このスクリプトは次のように使います。

どこかのスクリプトから以下のように呼び出せば、タイトル画面を表示することができます。目的以外の画面は自動的に非表示にしてくれます。引数を1に変えた場合は設定画面だけが開く、といった具合です。
//activationManager:ActivationManagerの参照
activationManager.Activate(0);
ランキング画面を追加する場合は、新しく作ったランキング画面をリストに追加するだけで良いのでとても楽です。

//ランキング画面を開く
activationManager.Activate(3);
引数の種類の追加
また、以下のように引数にゲームオブジェクトも指定できるようにしておくと、どこかのボタンのOnClickイベントから呼び出すときなどに便利になります。
ActivationManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ActivationManager : MonoBehaviour
{
public List<GameObject> targetList;
//番号指定
public void Activate(int num)
{
//対象のオブジェクトのみ表示し、対象以外のオブジェクトは非表示にする
for (int i = 0; i < targetList.Count; i++)
{
targetList[i].SetActive(i == num);
}
}
//ゲームオブジェクト指定
public void Activate(GameObject gameObject)
{
//対象のオブジェクトのみ表示し、対象以外のオブジェクトは非表示にする
foreach (GameObject g in targetList)
{
g.SetActive(g == gameObject);
}
}
}

以下のように番号指定しても挙動は同じですが、この場合targetListの並びが変わると影響を受ける点に注意が必要です。ゲームオブジェクト指定にしておくとtargetListの並びが変わっても影響を受けないので安心です。

階層構造
複数の階層にActivationManagerを使っても問題ありません。以下の例では、設定画面の中で更にいくつかの種類の設定項目があり、その設定項目ごとに画面を切り替える、ということを想定しています。

このように階層を増やすことで複雑な画面構成を作ることができます。
応用
このクラスはUIにしか使えないという制約は無いので、UI以外の場面でも応用が可能です。例えば、2Dや3Dで作った複数あるゲームステージの中から目的の1つだけを表示する、ということにも使えます。

おわりに
このActivationManagerクラスはここで挙げた例以外にも、主人公の外見の切り替え、光源の切り替え、カメラの切り替えなど、実に多彩な場面で応用することが可能です。自分が自作してきたクラスの中でも最高にシンプルで最高に便利、まさにシンプルイズベストなクラスだと思っています。みなさんのお役に立てば幸いです。