UnityのUIキャンバス設計で複数画面を効率切替する「専用マネージャ」構成

Unity

Unityでモバイル向けのUIを設計していると、複数の画面(Canvas)を切り替える必要が頻繁に発生します。
たとえば「ホーム画面」「強化画面」「探索画面」「ガチャ画面」など、ゲーム内で遷移するUIが増えていく中で、1シーン内でそれらをどう整理・切り替えるかは設計上の大きなポイントです。

本記事では、筆者が現在開発中のゲーム内で採用している、「画面表示制御マネージャ(以下、CanvasManager)」の構成と実装例について紹介します。


なぜ専用マネージャが必要なのか?

  • 複数Canvasを手動でアクティブ切り替えしているとスパゲッティコード化する
  • 画面同士で排他的に表示したいが、制御がバラバラになりがち
  • シーンを分けるほどでもないUIの遷移に手間をかけたくない

特にモバイルアプリでは「同一シーン内で完結」させたほうがパフォーマンスも管理もしやすいため、UI切り替えに特化したシンプルな仕組みが有効です。


Canvas構成の基本方針

  • UIはすべて1シーンにまとめる(画面ごとにCanvasを分割)
  • 各Canvasを空の親オブジェクトでまとめて管理
  • 表示切り替えはすべてCanvasManagerから制御
  • 表示Canvasは常に1つだけアクティブにする(他は非アクティブ)
CanvasRoot
├── HomeCanvas
├── UpgradeCanvas
├── ExploreCanvas
├── GachaCanvas
└── ...

実装例:CanvasManagerの構成

Canvasを切り替えるたびに、他のCanvasは必ず非アクティブにすることで、画面の重なりや想定外の挙動を防止します。以下にその具体例を示します:

public class CanvasManager : MonoBehaviour
{
    [SerializeField] private List<GameObject> canvasList;

    private GameObject currentCanvas;

    public void ShowCanvas(string canvasName)
    {
        foreach (var canvas in canvasList)
        {
            if (canvas == null) continue;
            bool isTarget = canvas.name == canvasName;
            canvas.SetActive(isTarget);
            if (isTarget)
            {
                currentCanvas = canvas;
            }
        }
    }

    public void ShowCanvas(GameObject targetCanvas)
    {
        foreach (var canvas in canvasList)
        {
            if (canvas == null) continue;
            bool isTarget = canvas == targetCanvas;
            canvas.SetActive(isTarget);
            if (isTarget)
            {
                currentCanvas = canvas;
            }
        }
    }

    public GameObject GetCurrentCanvas()
    {
        return currentCanvas;
    }
}

Inspector設定

  • canvasListに対象の各Canvasオブジェクトを登録(手動でも自動でもOK)
  • 表示切替時は CanvasManager.ShowCanvas("HomeCanvas") などで呼び出し

補足:パフォーマンスと注意点

  • 非表示Canvasは SetActive(false) で完全にオフになるため、不要なUpdate等は走らない
  • ただし、Update処理は走らせつつUIだけ切り替えたい場合、CanvasGroupでAlphaを0にし、RaycastTargetをオフにする構成も有効
// CanvasGroupを使った切り替え
CanvasGroup group = canvas.GetComponent<CanvasGroup>();
if (group != null)
{
    group.alpha = isTarget ? 1f : 0f;
    group.interactable = isTarget;
    group.blocksRaycasts = isTarget;
}
  • この方式では SetActive(true) のままにしておくことで、UpdateやCoroutineは維持される
  • アニメーションや状態保持をしたまま「シーン移行のようなUI表現」が可能になる
  • canvasList の登録漏れや名前違いには要注意(enum化や定数化推奨)
  • currentCanvas を使えば「戻る」「履歴」などの実装にも応用可能

  • 非表示Canvasは SetActive(false) で完全にオフになるため、不要なUpdate等は走らない
  • canvasList の登録漏れや名前違いには要注意(enum化や定数化推奨)
  • currentCanvas を使えば「戻る」「履歴」などの実装にも応用可能
  • CanvasのGraphicRaycasterとRaycastTarget設定も重要。非表示時には
    • GraphicRaycaster.enabled = false にする
    • またはCanvas全体を SetActive(false) にしてRaycast自体を遮断
// 追加処理例:Raycast無効化
var raycaster = canvas.GetComponent<GraphicRaycaster>();
if (raycaster != null)
    raycaster.enabled = isTarget;

こうすることで、「非表示UIが誤ってタップ判定を持つ」ような事故も防止できます。

  • 非表示Canvasは SetActive(false) で完全にオフになるため、不要なUpdate等は走らない
  • canvasList の登録漏れや名前違いには要注意(enum化や定数化推奨)
  • currentCanvas を使えば「戻る」「履歴」などの実装にも応用可能

まとめ

1シーンで複数UI画面を切り替える場面では、**「専用のCanvas切り替えマネージャ」**を作ることで、

  • スクリプトの責務分離
  • UIフローの明確化
  • バグ防止・パフォーマンス向上

など多くの利点があります。

ゲーム規模が大きくなる前に、こうしたマネージャの導入をぜひ検討してみてください。


ブログでもUnityや個人開発ネタを発信中です!

開発ノウハウやアプリ制作過程、Unity連携系のハマりポイントなど
より深掘りした内容をブログにまとめています。
https://syunpp.com

公開中のアプリ一覧はこちら!

実際にUnityで開発してリリース済みのアプリ一覧をまとめています。
https://syunpp.com/公開中のアプリ一覧/

YouTubeショートでもゲーム開発の裏側を公開中!

Unityで制作中のゲームの進捗や演出テスト、実装の様子を
ショート動画でタイムラプス形式にまとめて発信しています。
https://www.youtube.com/@syunpp_8413/shorts

コメント

タイトルとURLをコピーしました