Unityでゲーム開発をしていると、最初は気にならなかったのに、ある日ふと――
「あれ? GameManager、なんか巨大じゃない?」 「switch文、増えるたびに怖くなってきた…」
こんな違和感を覚えたこと、ありませんか?
ゲームの規模が少しずつ大きくなるにつれて、
「ゲーム全体の状態をどう管理するか」という問題は、じわじわと開発者を苦しめ始めます。
タイトル画面、プレイ中、ポーズ、イベント演出、リザルト…。 最初は if や switch で素直に書いていたはずなのに、 気づけば 変更が怖いコード になってしまった、という人も多いはずです。
この問題の正体は、実装力不足ではありません。 多くの場合、「状態(State)」という概念を、設計として整理しないままコードに落としてしまったことが原因です。
この記事では、Unityにおける「ゲームの状態管理(GameState)」について、
- なぜ GameManager が肥大化しやすいのか
- switch文設計の限界はどこにあるのか
- FSM(Stateパターン)やスタック型ステートはいつ使うべきか
- ScriptableObjectや設計分離はどう効いてくるのか
といったポイントを、「どれが正解か」ではなく「どう選ぶか」という視点で整理していきます。
コード例や実装手順だけでなく、 設計としてどう考えると破綻しにくいかを中心に解説するので、
- 今まさに設計に悩んでいる人
- 過去に状態管理で痛い目を見た人
- 将来のために「ちゃんとした形」を知っておきたい人
そんな方に、きっと役立つ内容になるはずです。
それではまず、
「なぜUnityの状態管理は破綻しやすいのか」から、一緒に整理していきましょう✨
1. なぜUnityの状態管理は破綻しやすいのか
Unityでのゲーム開発は、プロトタイプの段階では驚くほどスムーズに進みます。 タイトル画面を作って、プレイヤーを動かして、クリア判定を入れて…… この時点では、状態管理が大きな問題になることはほとんどありません。
ところが、開発が進み要素が増えてくると、少しずつ違和感が生まれます。
- ポーズ中なのに一部の処理が動いてしまう
- イベント演出中の入力制御が破綻する
- 状態を追加するたびに既存コードを大量に修正する
これらはすべて、「状態の責務が曖昧なまま実装されている」ことから起きやすい問題です。
GameManager集中管理が招く肥大化
よくある構成として、GameManager が次のような役割をすべて背負ってしまうケースがあります。
- 現在のゲーム状態の保持
- UIやプレイヤー、敵への参照
- 入力制御の切り替え
- シーン遷移や演出制御
最初は便利ですが、これは次第に巨大な神クラスになっていきます。 少し仕様を変えただけで別の機能が壊れる、 修正するたびに「どこに影響が出るかわからない」状態になりがちです。
これは技術力の問題というより、 役割の境界が設計上定義されていないことが原因です。
switch文による状態分岐の限界
次によくあるのが、Update() 内での switch 文による状態管理です。
状態が2〜3個のうちは、とても読みやすく、直感的です。 ですが、状態が増えるにつれて次のような問題が目立ち始めます。
- すべての状態が毎フレーム評価される
- 状態ごとの初期化・終了処理が散らばる
- フラグ更新忘れによるバグが出やすい
特に厄介なのが、「状態遷移の瞬間」です。 開始時にやる処理、終了時にやる処理が明確に分かれていないと、 バグが入り込む余地が一気に増えます。
イベント多用が生む見えない依存関係
疎結合を目指して、UnityEvent や C# イベントを多用する設計もよく見かけます。 確かに、参照関係は減ります。
しかし、イベントが増えすぎると今度は、
- どこから呼ばれているのか分からない
- いつ状態が変わったのか追えない
- デバッグ時に思考が追いつかない
といった可視性の低下が起こります。 これは「スパゲッティコード」と呼ばれる状態に近づいているサインです。
ここまでの問題をまとめると、Unityの状態管理が破綻しやすい理由はシンプルです。
状態が「条件」や「フラグ」として扱われ、
「振る舞いの単位」として設計されていない

次の章では、この問題を整理するために、 ゲーム状態管理の代表的なアプローチを一度俯瞰していきます。
2. ゲーム状態管理の代表的アプローチ整理
「状態管理が大事なのは分かったけど、結局どう作ればいいの?」 ここで多くの人が迷います。
Unityにおける状態管理には、いくつか定番のアプローチがあります。 まずはそれぞれの特徴と得意分野を整理しておきましょう。
ここで大切なのは、 「どれが一番すごいか」ではなく「どの状況に向いているか」です。
有限状態マシン(FSM / Stateパターン)
もっとも基本で、かつ応用範囲が広いのが有限状態マシン(FSM)です。
「今はこの状態で、条件を満たしたら次の状態へ遷移する」 という考え方で、状態ごとに振る舞いを分離します。
- Idle(待機)
- Move(移動)
- Attack(攻撃)
こうした状態をクラスとして定義するのが、いわゆるStateパターンです。
FSMの強みは、
- 状態ごとの責務が明確
- 開始・更新・終了処理を整理しやすい
- switch文より拡張しやすい
一方で、状態数が極端に増えると、 遷移条件の管理が煩雑になる点には注意が必要です。
👉 プレイヤー操作・敵AI・ゲーム全体の流れなど、 「今どのフェーズか」が重要な処理に向いています。
スタック型ステートマシン(Pushdown State Machine)
FSMを使っていて、 「一時的に別の状態へ割り込みたい」 そんな場面に出会ったことはありませんか?
例えば、
- ポーズ画面を開く
- 演出を再生する
- 確認ダイアログを出す
このようなケースでは、スタック型ステートが力を発揮します。
現在の状態をスタックに積んだまま、 新しい状態をPushし、 終わったらPopして元に戻す、という仕組みです。
この方式のメリットは、
- 元の状態を壊さずに一時処理を挟める
- 「戻る処理」を明示的に書かなくてよい
- ターン制や演出制御と相性が良い
👉 演出・UI・ターン制バトルなど、 「状態の重なり」が発生するゲームに向いています。
ScriptableObject Architecture
次に紹介するのは、少し毛色の違うアプローチです。
ScriptableObjectを使って、
- 状態データ
- イベント通知
- 共有フラグ
をアセットとして管理する設計です。
この方式の大きなメリットは、 シーンやオブジェクト間の依存を減らせることです。
状態そのものをMonoBehaviourに持たせないため、
- シーンをまたいだ管理が楽
- 参照切れが起きにくい
- テスト・デバッグがしやすい
といった利点があります。
👉 小〜中規模プロジェクトや、 「構成で整理したい」タイプの設計に向いています。
クラウドベース状態管理(マルチプレイヤー向け)
マルチプレイヤーゲームでは、 状態管理の考え方が少し変わります。
クライアント側だけで状態を管理すると、
- チートが成立しやすい
- 状態の正当性が保証できない
といった問題が出てきます。
そのため、
- サーバー側で正式な状態を管理
- クライアントは表示と入力に専念
という役割分担が必要になります。
Unityでは、Cloud Code や Cloud Save を使って、 こうしたサーバー主導の状態管理を構築できます。
👉 対戦ゲーム・協力プレイ・ランキング要素がある場合は必須の考え方です。
ここまで見てきたように、 状態管理には複数の選択肢があります。
重要なのは、 プロジェクトの規模・ゲーム性・将来の拡張を踏まえて選ぶことです。

次の章では、これらの中でも土台となるStateパターンに絞って、 具体的な実装手順と設計の考え方を詳しく解説していきます。
3. 基本となるStateパターン設計(最重要)
ここからは、この記事の土台となる考え方を解説します。 FSMやスタック型ステート、ScriptableObject設計など、 どのアプローチを選ぶにしても、基準になるのがStateパターンです。
「Stateパターン=難しい設計」 と思われがちですが、実は考え方はとてもシンプルです。
3-1. Stateパターンは「状態をクラスとして扱う」設計
まず大前提として、Stateパターンでは 状態を if やフラグで表現しません。
代わりに、
- 今どんな振る舞いをする状態なのか
- いつ開始され、いつ終わるのか
これらを1つのクラスに閉じ込めるという発想を取ります。
例えばプレイヤーなら、
- 待機しているときの振る舞い
- 移動しているときの振る舞い
- 攻撃しているときの振る舞い
それぞれを別クラスとして定義します。
こうすることで、
- 「この状態の責務はここまで」と言語化できる
- 他の状態に影響せず修正できる
- 状態追加の心理的ハードルが下がる
という効果が得られます。
3-2. Stateパターンを構成する3つの役者
Stateパターンは、主に次の3つで構成されます。
- State(状態):振る舞いを定義する
- Context:現在の状態を保持・切り替える
- User(利用者):Contextを使う側(Playerなど)
ここで重要なのは、 「状態を切り替える責務」をState自身に持たせないことです。
状態遷移の判断はContextが行い、 Stateは自分の振る舞いだけに集中します。
この役割分担が守られていないと、 State同士が直接参照し合い、結局スパゲッティ化してしまいます。
3-3. Entry / Update / Exit を明確に分ける
Stateパターンで特に効果が出るのが、 状態の開始・更新・終了を分けて考える点です。
- Entry:状態に入った瞬間に一度だけ呼ばれる
- Update:状態中、毎フレーム呼ばれる
- Exit:状態を抜けるときに一度だけ呼ばれる
この区切りがあるだけで、
- 初期化漏れ
- 終了処理忘れ
- フラグの後始末ミス
といった事故が大きく減ります。
switch文では曖昧になりがちな 「状態遷移の瞬間」を、 設計としてはっきり扱えるのがStateパターンの強みです。
3-4. 設計の理解を一段深めたい人へ
ここまでの内容で、 「考え方は分かったけど、なぜこれが有効なのかをもっと知りたい」 と感じた人もいるかもしれません。
そういった方には、 Stateパターンを“ゲーム設計の文脈”で解説している定番書がとても参考になります。
Game Programming Patterns Stateパターンを含むゲーム向け設計パターンを、 「なぜ必要か」「どう破綻を防ぐか」という視点で解説してくれる一冊です。
Game Programming Patterns
✅ Amazonでチェックする | ✅ 楽天でチェックする

次の章では、 このStateパターンをゲーム全体にどう適用するか、 GameManagerを痩せさせるためのEntity管理の分離について解説していきます。
4. Entity管理を分離してGameManagerを痩せさせる
Stateパターンを導入すると、 「状態そのもの」はかなり整理されます。 それでも次にぶつかりやすいのが、エンティティ管理の問題です。
プレイヤー、敵、UI、ギミック…… ゲーム内のオブジェクトが増えるにつれて、
- 状態変更のたびに個別に通知している
- GameManagerが全オブジェクトを参照している
- 初期化やリセット処理が散らばっている
こんな状態になっていませんか?
ここで有効なのが、 「GameManagerは状態だけを決める」 「エンティティの反応は別に管理する」 という分離の考え方です。
4-1. GameManagerが太る理由
GameManagerが肥大化する最大の理由は、 「状態を決める役」と「反応させる役」を同時に担ってしまうことです。
例えば、
- ゲーム開始時に全オブジェクトを初期化
- ポーズ時に各オブジェクトの挙動を止める
- リザルト時にUIと演出を切り替える
これらをすべてGameManagerが直接行うと、 参照も責務も一気に集中します。
その結果、
- 1か所の修正が多方面に影響する
- 新しいエンティティを追加しづらい
- テストやデバッグが困難になる
という状況が生まれます。
4-2. EntityManagerという考え方
そこで登場するのが、 EntityManager(またはそれに相当する仕組み)です。
考え方はシンプルで、
- 各エンティティは「状態変化にどう反応するか」だけを知る
- 誰に通知するかは中央で管理する
という役割分担を作ります。
GameManagerは、
- 今のゲーム状態を決定する
- 状態が変わった事実だけを通知する
だけに専念します。
具体的な処理内容は、 各エンティティ自身が判断します。
4-3. 共通インターフェースで反応を限定する
すべてのエンティティが すべての状態変化に反応する必要はありません。
そこで便利なのが、 インターフェースによる役割の明示です。
例えば、
IInitializable:初期化が必要なものIPausable:ポーズに反応するものIResettable:リセット対象のもの
といった形で分けます。
EntityManagerは、 「このインターフェースを実装しているものだけ呼ぶ」 という形で通知を行います。
こうすることで、
- 不要な処理呼び出しを防げる
- 責務がコードから読み取りやすくなる
- 後から対象を追加しやすい
といったメリットが生まれます。
4-4. この分離で得られる設計上の効果
Entity管理を分離すると、 設計の見通しが一気に良くなります。
- GameManagerは「流れ」だけを見る
- Stateは「振る舞い」だけを見る
- Entityは「自分がどう反応するか」だけを見る
それぞれの役割が明確になるため、
- 状態追加
- エンティティ追加
- 仕様変更
どれも以前より安全に行えるようになります。

次の章では、 この考え方をさらに発展させた スタック型ステートによる制御について解説します。
「FSMだけでは辛くなってきた」 そんなタイミングで、特に効果を発揮する設計です。
5. スタック型ステートで複雑な流れを制御する
FSM(Stateパターン)とEntity管理を整理すると、 多くのゲームはかなり安定します。
それでも、ある段階でこう感じることがあります。
「状態はちゃんと分けているのに、
一時的な割り込み処理がつらい…」
この悩みを解決してくれるのが、 スタック型ステートマシン(Pushdown State Machine)です。
5-1. FSMだけでは苦しくなる瞬間
通常のFSMでは、 「今はこの状態」という前提で処理が進みます。
しかしゲームでは、
- ポーズ画面を開く
- 演出を一時的に再生する
- 確認ダイアログを表示する
といった一時的な割り込みが頻繁に発生します。
これを通常のFSMで処理しようとすると、
- 元の状態を保存する変数が増える
- 復帰処理があちこちに散らばる
- 「どこに戻るのか」が分かりづらくなる
結果として、 FSMが再び複雑化してしまうことがあります。
5-2. スタック型ステートの基本構造
スタック型ステートでは、 状態を1つだけ保持するのではなく、積み重ねて管理します。
基本的な操作はとてもシンプルです。
- Push:新しい状態を積む
- Pop:一番上の状態を取り除く
- Peek:現在有効な状態を参照する
例えば、
- 「攻撃選択」状態をPush
- 演出が必要になったら「演出再生」状態をPush
- 演出が終わったらPopして攻撃選択に戻る
この間、下にある状態は一時停止(サスペンド)されます。
これにより、
- 元の状態を壊さない
- 復帰処理を書かなくてよい
- 状態の流れがスタックとして見える
という大きなメリットが得られます。
5-3. ターン制・演出・UIとの相性
スタック型ステートは、 特に次のようなケースで真価を発揮します。
- ターン制バトル
- カットインや必殺技演出
- ポーズ・設定・確認UI
これらはすべて、
「今の処理を止めて、
終わったら元に戻りたい」
という要求を持っています。
スタック型ステートは、 この要求を設計レベルで自然に表現できます。
5-4. 実装と可視化を楽にしたい人へ
スタック型ステートやFSMは、 自作でも十分に実装できます。
ただし、状態が増えてくると 「今どの状態が積まれているのか」 「遷移がどう流れているのか」を把握するのが難しくなります。
そういったときに役立つのが、 状態や遷移を可視化できるツールです。
Behavior Tree Slayerは、 FSMや複雑な状態遷移を視覚的に構築・確認できるUnityアセットです。
スタック型ステートやAI制御を、 コードだけでなく構造として理解したい人には、 かなり相性がいい選択肢になります。
Behavior Tree Slayer
✅ Unity Asset Storeでチェックする

次の章では、 コード中心の設計とは少し違うアプローチとして、 ScriptableObjectを使った状態管理について解説します。
「クラスを増やすより、構成で整理したい」 そんな人に向いている考え方です。
6. ScriptableObject Architectureという選択肢
ここまで紹介してきたStateパターンやスタック型ステートは、 どちらかというとコード中心の設計です。
一方でUnityには、 「構成そのものを整理する」ための強力な仕組みがあります。 それが ScriptableObject です。
ScriptableObject Architectureは、 状態管理をクラスの関係性ではなく、データの流れとして捉える考え方です。
6-1. なぜScriptableObjectが状態管理に向いているのか
ScriptableObjectの最大の特徴は、 シーンに依存しないデータとして存在できることです。
これにより、
- シーン切り替えで参照が切れない
- GameObjectに紐づかない状態を持てる
- テストやデバッグがしやすい
といったメリットが生まれます。
特に「今のゲーム状態」「ポーズ中かどうか」といった グローバルに共有したい情報とは相性が抜群です。
6-2. ScriptableObjectで状態を表現する発想
ScriptableObject Architectureでは、 状態そのものを次のように扱います。
- 現在のGameStateを保持するSO
- 状態変更を通知するSOイベント
- 状態に応じた設定データ
MonoBehaviour同士が直接参照し合う代わりに、 共通のScriptableObjectを介してやり取りします。
この構成にすると、
- GameManagerがほぼ不要になる
- どこからでも同じ状態を参照できる
- 依存関係がアセットとして可視化される
という設計が可能になります。
6-3. 向いているプロジェクト・向いていないプロジェクト
ScriptableObject Architectureは万能ではありません。
向いているのは、例えば次のようなケースです。
- 小〜中規模のプロジェクト
- チーム開発で役割分担が明確
- 状態数がそこまで多くない
逆に、
- 複雑な状態遷移ロジックがある
- 条件分岐が頻繁に絡む
といった場合は、 Stateパターンやスタック型ステートの方が 見通しが良くなることもあります。
大切なのは、 「ScriptableObjectだけで完結させようとしない」ことです。
Stateパターンと組み合わせて、
- 状態のデータはScriptableObject
- 振る舞いはStateクラス
という形にすると、 お互いの強みを活かせる設計になります。
ここまでで、 Unityにおける代表的な状態管理手法を一通り見てきました。

次の章では、 プロジェクトの規模別におすすめの設計パターンを整理し、 「結局どれを選べばいいのか?」に答えていきます。
7. 規模別おすすめ設計パターンまとめ
ここまで読んで、「結局どれを使えばいいの?」と感じている人も多いと思います。 状態管理には選択肢が多く、正解が分かりづらいですよね。
そこでこの章では、 プロジェクトの規模や性質ごとに、現実的なおすすめ構成を整理します。
ポイントは、 最初から完璧を狙わないことです。
7-1. 小規模プロジェクト(個人・短期開発)
対象例:
- 個人制作
- 短期間のプロトタイプ
- 状態数が少ないゲーム
おすすめ構成:
- GameManager(シングルトン)
- シンプルなStateパターン
この規模では、 過剰設計はむしろ足かせになります。
まずは、
- 状態をクラスとして分ける
- Entry / Update / Exit を意識する
これだけでも、 switch文ベースよりはるかに安全です。
7-2. 中規模プロジェクト(長期・要素多め)
対象例:
- 半年以上の開発
- UI・演出・ギミックが多い
- 仕様変更が頻繁
おすすめ構成:
- Stateパターン
- EntityManagerによる通知管理
- 一部ScriptableObjectの併用
この段階では、 責務の分離が効いてきます。
状態・流れ・反応を分けておくことで、
- 状態追加が怖くない
- エンティティ追加が楽
- テストや修正がしやすい
といったメリットが得られます。
7-3. 大規模プロジェクト(チーム・長期運用)
対象例:
- チーム開発
- 長期運用タイトル
- 頻繁なアップデート
おすすめ構成:
- Stateパターン + スタック型ステート
- 役割別Manager(GameState / GameModeなど)
- DI(依存性注入)フレームワーク
この規模では、 「誰が何を知っているか」を厳密に管理する必要があります。
DIを使うことで、
- 参照関係を明示できる
- テストがしやすくなる
- 設計の意図が共有しやすい
といった効果が期待できます。
7-4. マルチプレイヤー・オンライン要素がある場合
この場合は、 状態管理の前提が変わります。
クライアントだけで状態を管理すると、
- チート耐性が低い
- 状態の正当性が保証できない
といった問題が避けられません。
おすすめ構成:
- サーバー側で正式な状態を管理
- クライアントは表示と入力に専念
- Cloud Code / Cloud Save の併用
Unityのクラウドサービスを活用することで、 セキュアな状態管理が可能になります。

どの規模でも共通して言えるのは、
「状態管理は、早めに分離しておくほど後が楽」ということです。
まとめ
ここまで、Unityにおける「ゲームの状態管理(GameState)」について、 考え方から設計パターン、規模別の使い分けまで整理してきました。
振り返ってみると、 状態管理でつまずく原因はとてもシンプルです。
状態を「フラグ」や「条件」として扱い続けてしまうこと
これが、GameManagerの肥大化や、 switch文地獄、修正が怖いコードにつながっていきます。
私自身の経験としても、 「まだ早いかな」と思ってStateパターンを後回しにしたプロジェクトほど、 あとから何倍ものコストを払うことになりました。
逆に、
- 状態をクラスとして分ける
- 責務の境界を意識する
- 必要になったら段階的に分離する
この流れを意識するだけで、 設計のストレスは驚くほど減ります。
大切なのは、 最初から完璧な設計を作ることではありません。
「壊れそうになったときに、 壊れない方向へ進化させられる設計かどうか」
この記事が、 あなたのプロジェクトで 「今、何を選ぶべきか」を判断する材料になれば嬉しいです😊
あわせて読みたい
- Unityでステートマシンを活用!ゲーム開発を効率化する方法
- Unityのスクリプト設計を改善!SOLID原則で整理する方法
- Unityのコードをきれいに保つ!依存性注入(DI)の基本と実装方法
- UnityでAIを実装!ビヘイビアツリーと状態マシンの使い分け
参考文献
- Unityにおけるステートマシン設計の考え方と実装例(takap-tech)
- Unity Manual – State Machine Basics
- How are you all managing game flow and state?(Reddit / r/Unity3D)
- State machine pattern best practices(Reddit / r/Unity3D)
- GameManager as state machine architecture – best practices(Reddit / r/Unity3D)
- Unity Cloud Code ドキュメント:ゲーム状態管理
- How to structure a dynamic turn-based system(GameDev Stack Exchange)
よくある質問(FAQ)
- Qswitch文での状態管理は本当にダメですか?
- A
ダメではありません。 小規模・短期プロジェクトなら、十分に実用的です。
ただし、状態が増え始めた時点で 「Entry / Exit を意識できなくなったら黄色信号」だと思ってください。
- QFSMとBehaviorTreeはどちらを使うべきですか?
- A
役割が違います。
- FSM:ゲーム全体やキャラクターの「状態」を管理
- BehaviorTree:思考や意思決定の流れを表現
競合するものではなく、 組み合わせて使うケースが多いです。
- Q小規模でもStateパターンを使う意味はありますか?
- A
あります。
将来拡張しないとしても、 「状態をクラスで考える癖」が身につくのは大きな財産です。
まずはシンプルなStateパターンから始めて、 必要になったら分離・拡張していくのがおすすめです。







※当サイトはアフィリエイト広告を利用しています。リンクを経由して商品を購入された場合、当サイトに報酬が発生することがあります。
※本記事に記載しているAmazon商品情報(価格、在庫状況、割引、配送条件など)は、執筆時点のAmazon.co.jp上の情報に基づいています。
最新の価格・在庫・配送条件などの詳細は、Amazonの商品ページをご確認ください。