Unityにおける Service Locator パターン解説資料

1. はじめに

Service Locator パターンは、必要なサービス(依存オブジェクト)をグローバルに取得可能にする設計手法です。

Unityにおいては、シーンをまたいで共有される機能(サウンド、セーブ管理など)を動的に利用したい場合に有効です。


2. 特徴と利点・欠点

特徴

  • グローバルなサービスアクセスポイント(Locator)を通じて、サービスを取得
  • 利用側が依存関係を意識せずにサービスを取得できる
  • 実装の差し替えが可能(モック化など)

利点

  • コード上の依存関係を意識せずにサービスを呼び出せる
  • シングルトンよりも柔軟に差し替えや管理ができる

欠点

  • 依存関係が不明瞭になる(どのクラスが何に依存しているか分かりにくい)
  • 単体テストが困難(サービスの差し替えが見えにくい)
  • グローバル状態への依存リスクがある

3. Unityでの実装手順

3.1 サービスインターフェースの定義

public interface IAudioService
{
    void PlaySound(string soundName);
}

3.2 実装クラスの作成

public class AudioService : IAudioService
{
    public void PlaySound(string soundName)
    {
        Debug.Log($"[Audio] 再生: {soundName}");
        // 実際のAudioSource再生処理など
    }
}

3.3 ServiceLocator クラスの作成

using System;
using System.Collections.Generic;

public static class ServiceLocator
{
    private static readonly Dictionary<Type, object> _services = new();

    public static void Register<T>(T service)
    {
        _services[typeof(T)] = service;
    }

    public static T Get<T>()
    {
        return (T)_services[typeof(T)];
    }

    public static bool TryGet<T>(out T service)
    {
        if (_services.TryGetValue(typeof(T), out var instance))
        {
            service = (T)instance;
            return true;
        }

        service = default;
        return false;
    }
}

3.4 利用側の実装例

public class GameInitializer : MonoBehaviour
{
    private void Awake()
    {
        var audioService = new AudioService();
        ServiceLocator.Register<IAudioService>(audioService);
    }
}
public class Player : MonoBehaviour
{
    private void Start()
    {
        var audio = ServiceLocator.Get<IAudioService>();
        audio.PlaySound("Jump");
    }
}

4. 使用時の注意点

観点内容
可読性コードから依存関係が見えにくくなる
テスト性テスト時に依存の差し替えが困難になる
グローバル依存状態の共有や初期化タイミングが曖昧になりやすい

5. 実践的な補足(Unity向け)

  • ScriptableObjectを使ってサービスの定義をアセット化することで、差し替えや検証がしやすくなる
  • サービス登録の初期化タイミングは、アプリ起動時のGameManagerやBootstrapperなどで統一すると安定する
  • ログ、セーブデータ管理、リソース読み込みなどの共通機能に向いている

6. まとめ

Service Locator パターンは、Unityにおいて動的なサービス管理を実現する強力な手段です。ただし、過度な使用はコードの複雑化を招くため、用途を限定しつつ、テスト性や設計の明示性にも配慮することが重要です。