「GameManager」技術資料 - シングルトンによるグローバルなゲーム管理
以下は、GameManagerクラスに関する技術資料です。本資料では、Unity初心者にも理解しやすいよう、シングルトンパターンを活用したクラス設計や、コード例、ログ出力によるデバッグ手法、シーンを跨いだ状態管理のポイントなどを詳細に解説します。
シングルトンの基本
概要
GameManagerクラスは、Unityプロジェクトにおいて「グローバルなゲーム状態管理」を行うためのクラスであり、シングルトンパターンを採用することで、常に同一のインスタンスへアクセスできる仕組みを提供します。これにより、ゲーム中どのシーンからでも共通的なゲームロジックや状態に簡単にアクセスすることが可能となります。
主な特徴と実装ポイント
- シングルトンパターンの実装
GameManagerはシングルトンパターンにより、グローバルアクセス可能な唯一無二のインスタンスを提供します。static変数_instanceにインスタンスを保持Instanceプロパティを介して、どのスクリプトからでも同じGameManagerにアクセス可能Awake()メソッドで重複インスタンスを検出し、余分なインスタンスを破棄することで、複数存在することを防止
- DontDestroyOnLoadによるシーンまたぎの保持
DontDestroyOnLoad(gameObject)を呼ぶことで、GameManagerはシーン切り替え時にも破棄されず、ゲーム全体を通じて存在し続けます。これにより、シーン間で共通状態を一貫して管理できます。 - インスタンスID(GetInstanceID)によるデバッグ支援
GetInstanceID()によってインスタンスごとに異なるIDを取得でき、ログに出力することで、複数のGameManagerが生成・破棄される状況下でも、どのオブジェクトがいつ操作されたか明確に把握できます。これは、初学者が「なぜ2つ目のGameManagerが生まれたのか?」といったトラブルを理解・解消するのに役立ちます。 - nameofキーワードによる保守性向上
nameof(GameManager)と記述することで、クラス名を直接文字列で書かずに済みます。クラス名変更時にもログ出力などが自動的に対応可能となり、保守性が向上します。 - エラーログでの明確なフィードバック
Instanceアクセス時にインスタンスが存在しない場合はDebug.LogErrorで明確なエラーメッセージを表示します。これによって、なぜGameManagerが参照できないかを即座に把握でき、デバッグが容易になります。
シーン例
1つ目のGameManager

2つ目のGameManager

Player

コード例
以下は、上記のポイントを踏まえたGameManagerクラスのサンプルコードです。
using UnityEngine;
/// <summary>
/// ゲーム全体を通じてシーンを跨いで保持される、シングルトンによるゲーム管理クラス。
/// - シングルトンパターンにより、常に同一のインスタンスにアクセス可能
/// - DontDestroyOnLoadでシーン遷移時にも破棄されず、ゲーム全体を通して利用可能
/// </summary>
public class GameManager : MonoBehaviour
{
// シングルトンインスタンスを保持するための静的フィールド
private static GameManager _instance;
/// <summary>
/// シングルトンインスタンスへのグローバルアクセス用プロパティ。
/// インスタンスが存在しない場合はエラーログを出力します。
/// </summary>
public static GameManager Instance
{
get
{
if (_instance == null)
{
Debug.LogError($"[{nameof(GameManager)}] インスタンスが存在しません。シーン内に{nameof(GameManager)}を持つオブジェクトを配置してください。");
return null;
}
return _instance;
}
}
/// <summary>
/// AwakeはGameObject生成時に呼ばれ、シングルトンのインスタンス確立と重複排除を行います。
/// </summary>
private void Awake()
{
Debug.Log($"[{nameof(GameManager)}] {gameObject.name} (ID: {GetInstanceID()}) のAwakeが呼ばれました");
// すでにインスタンスが存在して、かつそれが自分自身でない場合は重複として破棄
if (_instance != null && _instance != this)
{
Debug.Log($"[{nameof(GameManager)}] 他のインスタンスが存在するため、このインスタンス(ID: {GetInstanceID()})は破棄されます: {gameObject.name}");
Destroy(gameObject);
return;
}
// このインスタンスをシングルトンとして登録
_instance = this;
Debug.Log($"[{nameof(GameManager)}] {gameObject.name} (ID: {GetInstanceID()}) をシングルトンインスタンスとして登録しました");
// シーンを跨いでこのオブジェクトを保持
DontDestroyOnLoad(gameObject);
Debug.Log($"[{nameof(GameManager)}] {gameObject.name} (ID: {GetInstanceID()}) はDontDestroyOnLoadで保持されます");
}
/// <summary>
/// プレイヤーが走る動きなど、ゲーム内処理の一例メソッド。
/// </summary>
public void Run()
{
Debug.Log($"[{nameof(GameManager)}] プレイヤーが走ります (呼び出し元: {gameObject.name}, ID: {GetInstanceID()})");
}
}
テスト実行の様子
エディター実行後、スペースキーを押下してRunメソッドが実行されることを確認します
想定ユースケースと運用上の注意点
- 最初のシーンでの配置
ゲーム開始時のシーンにGameManagerを配置することで、直後からGameManager.Instanceへアクセス可能となり、状態管理を一元化できます。 - 複数配置時の対処
仮に誤って複数のGameManagerを設置しても、余分なインスタンスは自動的に破棄されます。ログ出力には破棄されたインスタンスのIDが表示されるため、原因究明が容易です。 - Prefab化と再利用
GameManagerをPrefabとして用意し、最初のシーンに一度だけ配置します。それ以降はシーン遷移時に新たなGameManagerを配置する必要はなく、同一インスタンスを再利用できます。
まとめ
本資料では、GameManagerクラスの技術的背景や設計方針、具体的な実装例を通じて、シングルトンパターンを用いたグローバルなゲーム管理手法を解説しました。これを理解することで、シーン間をまたぐ状態管理、共通ロジックへの簡易アクセス、ログ出力を用いたトラブルシューティングなど、Unityにおける開発の基礎を着実に身につけることができます。
クラス図 (Class Diagram)
GameManagerクラス内でのシングルトン実装構造を示すためのクラス図です。

説明:
- static GameManager _instance: プライベートな静的フィールド。+ static GameManager Instance { get }: パブリックな静的プロパティ。_instanceを返し、未初期化時はエラーをログに出します。+ void Awake(): Unityのライフサイクルメソッド。インスタンスが未登録であれば_instanceを設定し、他インスタンスがある場合は破棄します。+ void Run(): ゲーム内動作の例メソッド。
シーケンス図 (Sequence Diagram)
シーンロード時にAwake()が呼ばれ、GameManagerのシングルトンが確立される過程、そしてRun()メソッドが呼ばれるまでの流れを示します。

説明:
- 最初の
GameManager(A)がシーンに読み込まれるとAwake()が呼ばれ、_instanceがAに設定されます。 - 2つ目の
GameManager(B)が存在すると、そのAwake()は既に_instanceがAで埋まっていることを検知し、Bは自動的に破棄されます。 Unity側からGameManager.Instanceを参照すると、常にAが返ります。GameManager.Run()を呼び出すと、Aインスタンスから実行され、ログが出力されます。
コンポーネント図 (Component Diagram) ※任意
シーン内に存在するGameManagerコンポーネントが、どのようにUnityエンジンと関わるかをシンプルに示すコンポーネント図の例です。

説明:
- Unityエンジンはシーン内に配置された
GameManagerゲームオブジェクト上のGameManagerスクリプト(コンポーネント)を実行します。 GameManagerはMonoBehaviourを継承しており、Unityのライフサイクル関数(Awake,Start,Update等)をフックして動作します。- このコンポーネントを通じて、Unityが
GameManagerにアクセスし、シングルトンロジックが機能します。
これらの図を通して、初学者は以下を理解しやすくなります。
- クラス図:
GameManagerがどのようなフィールドやプロパティを持ち、それがシングルトンパターンを実装するためのキーとなっているか。 - シーケンス図:シーン読み込み時の
Awake()呼び出し、重複インスタンスの破棄、Instanceプロパティ経由でのアクセス、Run()実行までの流れが時系列で可視化される。 - コンポーネント図:Unityというフレームワークが
GameManagerコンポーネントを介してシステムに組み込み、シングルトンオブジェクトを管理している構造を俯瞰できる。






ディスカッション
コメント一覧
まだ、コメントがありません