Unity & VContainer: 動的な敵生成と依存性注入の技術資料

目的

この技術資料では、Unity における VContainer を活用した 動的な敵の生成と、敵がプレイヤーを追尾する機能を依存性注入を通じて実装する方法を説明します。


アーキテクチャ構成

Player:

  • プレイヤーの位置情報を管理。
  • 敵はこの情報をもとに追尾します。

Enemy:

  • プレイヤーの位置を依存性注入で取得し、プレイヤーを追尾します。

GameManager:

  • スペースキーを押下した際に、敵を動的に生成します。

GameInstaller:

  • VContainer による依存性注入のセットアップを行います。

コードの説明

1. Player

プレイヤーの位置を公開するクラス。

using UnityEngine;

public class Player : MonoBehaviour
{
    public Transform PlayerTransform => transform;
}
  • ポイント:
    • PlayerTransform プロパティでプレイヤーの位置を公開します。
    • シーン内に1つ配置します。

2. Enemy

プレイヤーを追尾する敵クラス。依存性注入で Player を取得します。

using UnityEngine;
using VContainer;

public class Enemy : MonoBehaviour
{
    private Transform playerTransform;

    // Playerクラスの依存性を注入
    [Inject]
    public void Construct(Player player)
    {
        Debug.Log("Enemy: プレイヤーの依存性が注入されました。");
        playerTransform = player.PlayerTransform;
    }

    void Update()
    {
        if (playerTransform != null)
        {
            // プレイヤーの方向に向かって移動
            transform.position = Vector3.MoveTowards(transform.position, playerTransform.position, 2f * Time.deltaTime);
        }
    }
}
  • ポイント:
    • [Inject] メソッド: VContainer が自動的に Player の依存関係を注入。
    • Update メソッド: Vector3.MoveTowards を使用してプレイヤーを追尾。

3. GameManager

スペースキーを押下した際に敵を生成するクラス。

using UnityEngine;
using VContainer;
using VContainer.Unity;

public class GameManager : MonoBehaviour
{
    [SerializeField] private GameObject enemyPrefab; // EnemyのPrefab
    [SerializeField] private Transform spawnPoint; // 生成位置

    private IObjectResolver container;

    [Inject]
    public void Construct(IObjectResolver container)
    {
        this.container = container;
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            SpawnEnemy();
        }
    }

    private void SpawnEnemy()
    {
        // Prefab を VContainer 経由で生成(依存関係を自動注入)
        var enemyInstance = container.Instantiate(enemyPrefab, spawnPoint.position, Quaternion.identity);
        Debug.Log("GameManager: 敵が生成されました。");
    }
}
  • ポイント:
    • container.Instantiate:
      • VContainer を介して Prefab を生成。
      • 自動的に依存関係を解決します。
    • SpawnEnemy メソッド:
      • 敵を生成するロジック。

4. GameInstaller

依存関係のセットアップを行うクラス。

using VContainer;
using VContainer.Unity;

public class GameInstaller : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        // Player を登録
        builder.RegisterComponentInHierarchy<Player>();

        // GameManager を登録
        builder.RegisterComponentInHierarchy<GameManager>();
    }
}
  • ポイント:
    • RegisterComponentInHierarchy<T>():
      • シーン内のコンポーネントを VContainer に登録。

シーン設定手順

Player:

  • プレイヤーオブジェクトを作成し、Player スクリプトをアタッチ。
  • 位置を適切に設定。

Enemy Prefab:

  • 敵オブジェクトを作成。
  • Enemy スクリプトをアタッチ。
  • Prefab 化して、GameManagerenemyPrefab に設定。

GameManager:

  • 空のオブジェクトを作成し、GameManager スクリプトをアタッチ。
  • enemyPrefab: Enemy の Prefab を割り当て。
  • spawnPoint: 敵を生成する位置のオブジェクトを設定。

GameInstaller:

  • 空のオブジェクトを作成し、GameInstaller スクリプトをアタッチ。

クラス図

動作確認手順

スペースキーを押下:

  • 敵が指定した位置(spawnPoint)に生成される。

敵がプレイヤーを追尾する:

  • 敵がプレイヤーの位置に向かって移動する。

コンソールログ:

  • Enemy: プレイヤーの依存性が注入されました。」 が表示されることを確認。

実装のポイント

  • container.Instantiate の利用:
    • 動的なオブジェクト生成時にも依存性注入を適用できる。
  • 設計の分離:
    • GameManager は生成ロジック、Enemy は追尾ロジックに責務を限定。

トラブルシューティング

敵が追尾しない:

  • Player がシーン内に配置されているか確認。
  • Player スクリプトが正しく動作しているか確認。

Construct が呼び出されない:

  • container.Instantiate を使用しているか確認。
  • GameInstaller がシーンに正しく配置されているか確認。

これにより、VContainer を活用した依存性注入による動的な敵生成が実現できます。