Unityプロジェクト統合サンプル資料

1. はじめに

本資料では、Unityプロジェクトにおける代表的な依存管理・サービス提供の設計パターン(Service Locator、Singleton、Dependency Injection、ScriptableObject)を、実際のフォルダ構成例とコードサンプルを用いて紹介します。

2. プロジェクト構成

Assets/
└─ Scripts/
   ├─ Bootstrapper/
   │   └─ Bootstrapper.cs
   ├─ Services/
   │   ├─ ServiceLocator.cs
   │   ├─ IAudioService.cs
   │   └─ AudioService.cs
   ├─ Singleton/
   │   └─ AudioManager.cs
   ├─ DI/
   │   ├─ GameLogic.cs
   │   └─ GameController.cs
   └─ ScriptableObjects/
       ├─ AudioConfigSO.cs
       └─ AudioPlayer.cs

3. Bootstrapper(初期化用)

最初のシーンに配置し、起動時にサービスを登録します。

using UnityEngine;
using Services;

public class Bootstrapper : MonoBehaviour
{
    void Awake()
    {
        // Service Locator に登録
        ServiceLocator.Register<IAudioService>(new AudioService());
        // 他サービスの登録もここで行う
    }
}

4. Service Locator パターン

4.1 インターフェース定義

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

4.2 実装クラス

using UnityEngine;

namespace Services
{
    public class AudioService : IAudioService
    {
        public void PlaySound(string soundName)
        {
            Debug.Log($"[AudioService] Play: {soundName}");
            // AudioSource 再生処理
        }
    }
}

4.3 ServiceLocator 本体

using System;
using System.Collections.Generic;

namespace Services
{
    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 inst))
            {
                service = (T)inst;
                return true;
            }
            service = default;
            return false;
        }
    }
}

4.4 利用例

using UnityEngine;
using Services;

public class PlayerSL : MonoBehaviour
{
    void Start()
    {
        var audio = ServiceLocator.Get<IAudioService>();
        audio.PlaySound("Jump");
    }
}

5. Singleton パターン

using UnityEngine;

public class AudioManager : MonoBehaviour
{
    public static AudioManager Instance { get; private set; }

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public void PlaySound(string name)
    {
        Debug.Log($"[AudioManager] Play: {name}");
        // 再生処理
    }
}

// 利用例
// AudioManager.Instance.PlaySound("Jump");

6. Dependency Injection パターン

6.1 純粋クラス

namespace DI
{
    public class GameLogic
    {
        private readonly Services.IAudioService _audio;

        public GameLogic(Services.IAudioService audioService)
        {
            _audio = audioService;
        }

        public void Jump()
        {
            _audio.PlaySound("Jump");
        }
    }
}

6.2 MonoBehaviour 側で注入

using UnityEngine;
using Services;
using DI;

public class GameController : MonoBehaviour
{
    private GameLogic _logic;

    void Awake()
    {
        var audio = ServiceLocator.Get<IAudioService>();
        _logic = new GameLogic(audio);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            _logic.Jump();
        }
    }
}
using UnityEngine;
using UnityEngine.InputSystem;    // ← 追加
using Services;
using DI;

public class GameController : MonoBehaviour
{
    private GameLogic _logic;
    private InputAction _jumpAction;  // ジャンプ用アクション

    void Awake()
    {
        // DI からサービスを取得
        var audio = ServiceLocator.Get<IAudioService>();
        _logic = new GameLogic(audio);

        // スペースキーでジャンプする InputAction を生成
        _jumpAction = new InputAction(type: InputActionType.Button, binding: "<Keyboard>/space");
        _jumpAction.performed += ctx => _logic.Jump();
        _jumpAction.Enable();
    }

    void OnDestroy()
    {
        // イベントとアクションをクリーンアップ
        _jumpAction.performed -= ctx => _logic.Jump();
        _jumpAction.Disable();
        _jumpAction.Dispose();
    }
}

7. ScriptableObject パターン

7.1 設定用 ScriptableObject

using UnityEngine;

[CreateAssetMenu(menuName = "Config/AudioConfig")]
public class AudioConfigSO : ScriptableObject
{
    public AudioClip jumpClip;
    public AudioClip hitClip;
}

7.2 ScriptableObject を使う MonoBehaviour

using UnityEngine;

public class AudioPlayer : MonoBehaviour
{
    [SerializeField] private AudioConfigSO config;
    private AudioSource _source;

    void Awake()
    {
        _source = gameObject.AddComponent<AudioSource>();
    }

    public void PlayJump()
    {
        _source.PlayOneShot(config.jumpClip);
    }

    public void PlayHit()
    {
        _source.PlayOneShot(config.hitClip);
    }
}
訪問数 5 回, 今日の訪問数 1回