Unityでゲームを作っていると、あちこちに「Manager」という名前のクラスが増えていって、いつのまにか全部シングルトンにしてしまっていた……なんてこと、ありませんか?サービスロケーターやイベント駆動という言葉も聞いたことはあるけれど、結局どれを使えばいいのか分からないまま、なんとなくシングルトンに頼っている方も多いはずです。
この記事では、シングルトン・サービスロケーター・イベント駆動という3つの設計パターンについて、それぞれの違いと向き不向き、そして自分のプロジェクト規模に合った選び方を順番に解説していきます。
シングルトン・サービスロケーター・イベント駆動の違いとは
3つの名前を聞いただけだと、正直どれも「グローバルに何かへアクセスするための仕組み」というイメージが重なって、違いが分かりにくいですよね。まずはそれぞれが担っている役割を、ざっくりと整理してみましょう。
3つの役割の違いを一言で整理
シングルトンは、クラスのインスタンスを1つだけに限定して、どこからでも直接そのインスタンスにアクセスできるようにする仕組みです。サービスロケーターは、実装クラスに直接アクセスするのではなく、間に「ロケーター」を挟んで、抽象化されたインターフェース経由でサービスを呼び出す仕組みになります。
イベント駆動は、この2つとは少し毛色が違っていて、誰かが特定のクラスを直接呼び出すのではなく、「何かが起きたよ」という通知を発信し、それを受け取りたいオブジェクトだけが反応するという仕組みです。Unityの場合はScriptableObjectを使ってこの通知の仕組みを作ることが多くなっています。
ざっくり言うと、シングルトンは「直接つながる」、サービスロケーターは「間接的につながる」、イベント駆動は「つながりを持たずに通知だけする」という違いがあると捉えると、この後の内容が理解しやすくなるはずです。

それぞれの詳しい向き不向きは、これから順番に見ていきましょう。
シングルトンが向いている場面・向いていない場面
「とりあえずシングルトンにしておけば安心」と考えてしまいがちですが、実はシングルトンには向き不向きがはっきりある設計パターンです。ここでは、どんな機能なら安心して使えるのか、逆にどんな場面で後悔しやすいのかを整理していきます。
シングルトンが向いているのは、インスタンスが複数存在するとバグの原因になってしまう機能です。例えばファイル操作やネットワーク通信のように、同時に複数の窓口ができてしまうと処理が競合してしまうようなものが当てはまります。
判断に迷ったときは、次のチェックリストを自分のクラスに当てはめてみてください。
- ✅ そのクラスは、ゲーム中に絶対に1つしか存在してはいけないか
- ✅ どのシーンからでも同じインスタンスにアクセスする必要があるか
- ✅ 破棄されるタイミングを自分で管理できているか
この3つに自信を持って「はい」と答えられないなら、シングルトンではなく別の手段を検討したほうが安全かもしれません。
シングルトンは便利な反面、クラス間の結合度が非常に高くなりやすいパターンです。あちこちのクラスから直接呼び出されるようになると、後から修正するときに影響範囲が読めなくなってしまいます。また、インスタンスを破棄し忘れるとメモリリークの原因になることもあるため、ライフサイクルの管理には注意が必要です。
ここで一つ、混同しやすいポイントがあります。「MonoBehaviourを継承する必要がないなら、シングルトンではなく単なる静的(static)クラスを使えばいい」という考え方もあります。一方で、拡張性やテストのしやすさを重視するなら、この後紹介するサービスロケーターに置き換えるべきという見方もあるため、どちらが正解と決めつけずに、自分のプロジェクトの状況に合わせて選ぶことが大切です。
シングルトンの具体的な実装方法や、初心者がやりがちなミスについては、こちらの記事で詳しく解説しています。
サービスロケーターは本当にアンチパターンなのか
「サービスロケーターはアンチパターンだ」という意見を見かけて、使うのを迷ってしまった方もいるかもしれません。ですが、これは一概に良い・悪いと言い切れるものではなく、使い方次第という側面が大きいパターンです。
サービスロケーターは、サービスの処理を直接呼び出すのではなく、間に挟んだロケーターを経由して、抽象化されたインターフェースと具体的な実装クラスを結びつける仕組みです。この仕組みが向いているのは、グローバルにアクセスしたいけれど、実装を柔軟に差し替えたい場面になります。
例えば、サウンド再生やサーバー通信、ログ出力などが分かりやすい例です。特に通信APIのレスポンスをテスト用のモックデータに差し替えたいときなど、実装を簡単に入れ替えられる恩恵を実感しやすくなります。
一方で、アンチパターンと言われる理由もきちんと理解しておく必要があります。サービスロケーター自体への依存度が増えていくため、プロジェクトが大きくなるほど「どこで何が使われているか」という依存関係の追跡が難しくなっていくのです。
導入するかどうかを判断するときは、次のような観点で考えてみるとよいでしょう。
- 実装を差し替える必要がある機能(テスト用モックへの切り替えなど)が実際にあるか
- チームの人数やプロジェクトの規模が大きくなる見込みがあるか
- 依存関係を追いやすくする工夫(命名ルールやドキュメント化など)を用意できるか
これらを踏まえたうえで、小規模なプロジェクトであれば導入コストに見合わない場合もありますし、逆にテスト差し替えの恩恵が大きいプロジェクトなら十分に検討する価値があります。
サービスロケーターとDIコンテナは似ているようで、考え方が異なります。サービスロケーターはコードの中から自分で「取りに行く」仕組みであるのに対し、DIコンテナは外部から依存関係が「渡されてくる」仕組みです。

どちらも実装を差し替えやすくする点では共通していますが、この違いを知っておくと、後から別の設計パターンを学ぶときにも混乱しにくくなります。
イベント駆動が向いている場面とは
シングルトンやサービスロケーターが「呼び出す側」を起点にした仕組みだったのに対して、イベント駆動は少し発想が異なります。誰かが誰かを直接呼び出すのではなく、「何かが起きた」という事実だけを発信して、それを受け取りたいオブジェクトだけが反応する仕組みです。
Unityでは、この仕組みをScriptableObjectを使って実現することが多くなっています。イベント駆動が向いているのは、インゲームでの疎結合な連携が必要な場面です。例えば、あるオブジェクトの状態が変化したときに、それとは直接関係のない他のオブジェクトにも通知したい、といったケースが当てはまります。
この仕組みには、実装面でも嬉しいメリットがあります。
- シーンをまたいでもデータを保持できる
- プログラマーが手を加えなくても、デザイナーがインスペクター上で値を調整・設定できる
- 通知する側とされる側が、お互いのクラスを直接知らなくても連携できる
特に2つ目のメリットは見落とされがちですが、チームで開発している場合、デザイナーがコードを触らずに設定を変えられるというのは、日々の開発スピードに地味に効いてくる部分です。
ただし、イベント駆動もどんな場面でも万能というわけではありません。イベントを介した通知は、どこで発生してどこで受け取られているのかが見えにくくなりがちで、処理の実行順序を追いにくいという側面もあります。また、リスナーとして登録したオブジェクトの登録解除を忘れると、思わぬ不具合につながることもあるため、疎結合であることのメリットと引き換えに、こうした追跡のしづらさがある点は頭の片隅に置いておくとよいでしょう。
ScriptableObjectを使ったイベントの具体的な作り方については、こちらの記事でEventとActionの使い方を交えて解説しています。
結局どれを選ぶべきか|規模別の判断基準
ここまで3つのパターンをそれぞれ見てきましたが、結局のところ「自分のプロジェクトにはどれが合っているのか」が一番知りたいところですよね。ここからは、プロジェクトの規模やチーム人数を軸に、実際の選び方を整理していきます。
まずは3つのパターンの特徴を、判断しやすいように比較表でまとめてみました。
| パターン | 結合度 | 向いている場面 | 注意点 |
|---|---|---|---|
| シングルトン | 高い | インスタンスが1つしか存在してはいけない機能 | 密結合・破棄忘れによるメモリリーク |
| サービスロケーター | 中程度 | 実装を柔軟に差し替えたい機能 | 依存関係の追跡が難しくなりやすい |
| イベント駆動 | 低い | インゲームでの疎結合な連携 | 実行順序や購読解除の管理が難しい |
この表を踏まえたうえで、実際にどう選べばよいのかを、チーム規模別に見ていきましょう。
1〜3人・数ヶ月規模の場合の選び方
個人開発や少人数チームで、開発期間も数ヶ月程度というプロジェクトなら、複雑な仕組みを最初から作り込む必要はありません。こうした規模感では、Managerクラスをそのまま外部から差し替えられるようにする、いわゆる「Service+DI」という軽量なアプローチが選ばれることが多くなっています。
これは、Presenter層のような表示制御の仕組みを部分的に取り入れつつ、DI(依存性の注入)を使ってManagerクラスをテストしやすくするという考え方です。あくまで一般的な目安ですが、高速に機能を実装したいプロトタイプ段階のプロジェクトに向いているアプローチと言えます。
依存性の注入(DI)の基本的な考え方や実装方法については、こちらの記事でより詳しく解説しています。
5人以上・1年以上の中〜大規模の場合の選び方
チーム人数が5人を超えて、開発期間も1年以上続くような中〜大規模プロジェクトになると、話は変わってきます。複雑なビジネスロックや高いテストカバレッジが求められる場面が増えるため、View(画面表示)が直接Model(データ)を操作しない、レイヤーごとに役割を分ける設計が必要になりやすいという傾向があります。
これはあくまで一般的な傾向であり、プロジェクトの内容によって最適な形は変わってきますが、チーム開発が長期化するほど、誰がどこを触っても壊れにくい構造にしておく重要性は増していきます。

こうしたレイヤードアーキテクチャの具体的な作り方は、別の機会に詳しく扱いたいと思います。
複数パターンを併用してもいい?組み合わせの考え方
ここまで読んで、「結局、1つのパターンに絞らないといけないの?」と感じた方もいるかもしれません。実際のプロジェクトでは、必ずしもどれか1つだけを選ぶ必要はなく、複数のパターンを組み合わせて使うケースも珍しくありません。
例えば、全体で1つだけ存在すればよいゲーム管理用のクラスにはシングルトンを使いつつ、オブジェクト同士の疎結合な連携が必要な部分にはイベント駆動を組み合わせる、といった使い分けです。それぞれのパターンが得意な役割を担う場所に配置することで、無理に1つの仕組みだけで全体を統一しようとするより、自然な設計になりやすくなります。
ただし、組み合わせて使う際に気をつけたいのは、それぞれのクラスがどこまでの役割を担うのかという境界があいまいになりやすいという点です。シングルトンのクラスにイベント通知の処理まで詰め込んでしまうと、結局そのクラスだけが肥大化して、何をしているクラスなのか分かりにくくなってしまいます。
複数のパターンを併用する場合は、「このクラスは何の責任を持つのか」を意識しながら役割を分けていくことが大切です。この責務の分け方について迷ったときは、こちらの記事も参考にしてみてください。
よくある誤解・注意点
ここまでの内容とは別に、設計パターンを学び始めたときに混同しやすいポイントをいくつか補足しておきます。すでに本文で触れた内容と重なる場合は、改めて簡潔に整理していきます。
まず、「静的(static)クラス」と「シングルトン」を同じものだと捉えてしまうケースがあります。静的クラスはインスタンスという概念自体を持たないため、MonoBehaviourのライフサイクル(AwakeやStartなど)を利用できません。一方でシングルトンは、インスタンスを1つに制限しながらも、通常のMonoBehaviourと同じようにライフサイクルを扱える点が異なります。
もう一つ、混同しやすいのが「オブジェクト指向設計」と「アーキテクチャ設計」の違いです。継承やポリモーフィズム、インターフェースといった話は、あくまでクラスをどう作るかというオブジェクト指向の基礎にあたります。それに対して、今回扱ったシングルトンやサービスロケーター、イベント駆動といったパターンは、クラス同士をどう連携させるかという、一段階上の設計の話になります。
この2つは関連してはいるものの、扱っている範囲が異なるため、混ぜて考えてしまうと理解がぼやけてしまいがちです。継承やインターフェースといったオブジェクト指向の基礎からもう一度整理したい場合は、こちらの記事も参考にしてみてください。
よくある質問
-
Qシングルトンをやめてサービスロケーターに移行する際、注意すべきことは?
-
A一気に全てのシングルトンを置き換えようとすると、修正範囲が広がりすぎて混乱の元になります。まずは実装を差し替えたい機能や、テスト時にモックへ切り替えたい機能から優先的に移行し、段階的に進めていくことをおすすめします。移行の途中でシングルトンとサービスロケーターが混在する期間があっても、それ自体は問題ありません。
-
Qイベント駆動にすると処理が追いにくくなりませんか?
-
Aその傾向はあります。イベントを発信する側と受け取る側が直接つながっていないぶん、どこで何が起きているのかをコードだけで追いにくくなることがあります。これを補うために、イベントの発生箇所や受信箇所にログを仕込んでおいたり、命名ルールを統一しておいたりすると、後から見返したときに把握しやすくなります。
-
Q小規模な個人開発でもDIコンテナ(Zenject/VContainer)は導入すべき?
-
A必須ではありません。数ヶ月規模の個人開発であれば、DIコンテナを本格的に導入するよりも、シンプルなService+DIのアプローチで十分なケースが多くなっています。開発が長期化してテストの重要性が増してきたタイミングで、改めて導入を検討するくらいでちょうどよいバランスだと考えられます。












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