Unityにおける依存管理・サービス提供パターン比較資料
目次
1. 比較の目的
Unityでは、ゲーム全体で共有する機能(音声管理、セーブ処理、状態管理など)を「どのように提供・利用するか」が設計上の重要な課題です。
本資料では、以下の4つの方法を比較し、使用場面や適切な選定指針を明確にします。
- Service Locator
- Singleton
- Dependency Injection (DI)
- ScriptableObject(データ提供型)
2. 各パターンの概要とコード例
2.1 Service Locator
特徴
- グローバルアクセスでサービスを取得
- 実装の差し替えが可能
コード例(簡略)
ServiceLocator.Register<IAudioService>(new AudioService());
var audio = ServiceLocator.Get<IAudioService>();
audio.PlaySound("Jump");
2.2 Singleton
特徴
- クラス内に唯一のインスタンスを保持
- アクセスが簡単だが、差し替えが困難
コード例
public class AudioManager : MonoBehaviour
{
public static AudioManager Instance { get; private set; }
private void Awake()
{
if (Instance == null) Instance = this;
else Destroy(gameObject);
}
public void PlaySound(string name) { /*...*/ }
}
// 利用側
AudioManager.Instance.PlaySound("Jump");
2.3 Dependency Injection(明示的な依存注入)
特徴
- 必要なサービスをコンストラクタやプロパティで渡す
- テストしやすく、依存関係が明示される
コード例(非MonoBehaviour)
public class GameLogic
{
private readonly IAudioService _audio;
public GameLogic(IAudioService audio) { _audio = audio; }
public void Jump() => _audio.PlaySound("Jump");
}
2.4 ScriptableObject
特徴
- データや設定をアセットとして分離可能
- デザイン時にインスペクタで差し替え可能
コード例
[CreateAssetMenu]
public class AudioConfig : ScriptableObject
{
public AudioClip jumpClip;
}
public class Player : MonoBehaviour
{
public AudioConfig config;
void Jump() { AudioSource.PlayClipAtPoint(config.jumpClip, transform.position); }
}
3. 比較表
観点 | Service Locator | Singleton | Dependency Injection | ScriptableObject |
---|---|---|---|---|
アクセスの容易さ | 高い(静的) | 高い(静的) | 低い(注入が必要) | 中(参照を要設定) |
依存の明示性 | 低い | 低い | 高い | 高い |
テストのしやすさ | 低い | 非常に低い | 高い | 高い |
柔軟な差し替え | 可能(手動) | 困難(コード変更) | 容易(注入で切替) | 容易(アセット切替) |
初学者への導入難易度 | 中 | 低い | 高い | 中 |
Unityエディタ連携 | なし | あり | なし(補助が必要) | あり(インスペクタ活用) |
主な用途 | 実行時の動的切替 | 単純な共通機能 | テスト可能な設計 | 設定・定数・テーブル類 |
4. 使い分け指針
開発状況 | 推奨パターン | 理由と補足 |
---|---|---|
シンプルな常駐管理 | Singleton | 導入が最も容易。AudioManagerなどに向いている |
テストや柔軟性を重視 | Dependency Injection | 明示的設計。モックの切替や再利用に最適 |
データや定数の共有 | ScriptableObject | 設定変更が容易。アセット経由でUIや敵パラメータなど |
小規模でグローバル取得したい | Service Locator | クラス間を疎結合で保ちつつ、静的アクセスが可能 |
DIは使いたいがUnityに合わない | ScriptableObject + ServiceLocator | モックをScriptableObjectで切り替えれば組み合わせも可能 |
5. 結論
Unityでは用途に応じて以下のようなパターン使い分けが有効です。
- 開発初期〜小規模 → Singleton / ScriptableObject
- 中〜大規模 / テストが必要 → DI / Service Locator
- 柔軟に切り替えたい設定 → ScriptableObject + Locator
導入の手軽さだけでなく、長期的な保守性・拡張性・チーム開発とのバランスを考慮して選択しましょう。
ディスカッション
コメント一覧
まだ、コメントがありません