Почему возникает ошибка Unable to resolve 'GameFactory' while building object with type 'Spawner' в Zenject?

Всем привет. У меня есть два инсталлера

Project

public override void InstallBindings()
{
    RegisterInputService();
    RegisterAssetsProvider();
    RegisterStaticDataServices();
    RegisterPersistentProgressServices();
    RegisterRandomizer();
}

private void RegisterAssetsProvider() =>
    Container.Bind<AssetsProvider>().AsSingle();

private void RegisterInputService() =>
    Container.Bind<InputService>().AsSingle();

private void RegisterStaticDataServices() =>
    Container.Bind<StaticDataService>().AsSingle();

private void RegisterPersistentProgressServices() =>
    Container.Bind<PersistentProgressService>().AsSingle();

private void RegisterRandomizer() =>
    Container.Bind<RandomService>().AsSingle();

И Scene

public override void InstallBindings() => 
    RegisterFactories();

private void RegisterFactories() => 
    RegisterGameFactory();

private void RegisterGameFactory() => 
    Container.Bind<GameFactory>().AsSingle();

Проблема возникает с GameFactory после создания Spawner.

private readonly AssetsProvider _assetsProvider;

public GameFactory(AssetsProvider assetsProvider) => 
    _assetsProvider = assetsProvider;

public GameObject Hero { get; private set; }
public GameObject Enemy { get; private set; }
public GameObject Hud { get; private set; }
public GameObject Spawner { get; private set; }


public async UniTask WarmUp()
{
    await _assetsProvider.Load<GameObject>(AssetsAddresses.HeroAddress);
    await _assetsProvider.Load<GameObject>(AssetsAddresses.SpawnerAddress);
    await _assetsProvider.Load<GameObject>(AssetsAddresses.EnemyAddress);
    await _assetsProvider.Load<GameObject>(AssetsAddresses.HudAddress);
}

public async UniTask CreateHero()
{
    GameObject prefab = await _assetsProvider.Load<GameObject> 
    (AssetsAddresses.HeroAddress);
    Hero = _assetsProvider.Instantiate(prefab);
}

public async UniTask CreateSpawner()
{
    GameObject prefab = await _assetsProvider.Load<GameObject> 
    (AssetsAddresses.SpawnerAddress);
    Spawner = _assetsProvider.Instantiate(prefab);
}

public async UniTask CreateEnemy(Vector2 position)
{
    GameObject prefab = await _assetsProvider.Load<GameObject> 
    (AssetsAddresses.EnemyAddress);
    Enemy = _assetsProvider.Instantiate(prefab, position);
}

Spawner создаеться в одном из стейтов при запуске игры.

  public async void Enter()
  {
    InitializeAddressables();

    await CreateGameObjects();

    EnterInGameLoopingState();
  }

  private async UniTask CreateGameObjects()
  {
    await CreateHero();
    await CreateSpawner();
    await CreateHud();
  }

Сам Spawner должен на старте (на данный момент, потом будет по таймеу) начать спавнить врагов.

 private RandomService _randomService;
 private GameFactory _gameFactory;

 [Inject]
 public void Constructor(GameFactory gameFactory, RandomService randomService)
 {
    _gameFactory = gameFactory;
    _randomService = randomService;
 }

 private void Start() => 
    SpawnEnemy();

 private async void SpawnEnemy()
 {
    Vector2 randomPosition = new Vector2(_randomService.Next(-10f, 10f), 
    _randomService.Next(10f, 10f));

    await _gameFactory.CreateEnemy(randomPosition);
 }

однако вылетает ошибка. Unable to resolve 'GameFactory' while building object with type 'Spawner'. Если переместить Регистрацию Фабрики из СценКонтекст в ПрожектКонтекст то всё будет работать без проблем. Хотелось бы понять почему такое происходит. Огромное спасибо.


Ответы (1 шт):

Автор решения: Farit Shakurov

Проблема найдена.

Spawner создаеться в AssetsProvider, который в контрукторе принимает DiContainer, из которого вызывается метод InstantiatePrefab.

AssetsProvider биндится в ProectContext. По этой причине DiContainer знает только о биндах, которые происходят в ProjectContext, а так как GameFactory биндится в SceneContext, то DiContainer ничего о фабрике не знает, и не может передать его через [Inject] в конструктор Spawner.

Решение, до которого я дошел на данный момент:

  1. Перенести бинд фабрики в ProjectContext
  2. Перенести бинд AssetsProvider и все сервесы, которые будут использовать AssetsProvider, в SceneContext.
→ Ссылка