通过工厂或池使用子容器实例化随机或选择的预制件

Instantiating random or chosen prefabs with sub-container thru Factory or Pool

我有一组预制件,我希望能够通过 Zenject Factory 实例化随机选择的预制件,并在它们的子容器中执行它们的绑定。

我想做的与 Zenject 文档中的代码示例相同,但针对的是随机选择的预制件。 https://github.com/modesttree/Zenject/blob/master/Documentation/SubContainers.md#using-game-object-contexts-no-monobehaviours

using UnityEngine;
using Zenject;

public class GameInstaller : MonoInstaller
{
    [SerializeField]
    GameObject ShipPrefab;

    public override void InstallBindings()
    {
        Container.BindInterfacesTo<GameRunner>().AsSingle();

        Container.BindFactory<float, ShipFacade, ShipFacade.Factory>()
            .FromSubContainerResolve().ByNewPrefabInstaller<ShipInstaller>(ShipPrefab);
    }
}

我能够部分使用

[SerializeField] private GameObject[] ships;

...

Container.BindFactory<float, ShipFacade, ShipFacade.Factory>()
            .FromSubContainerResolve().ByNewGameObjectMethod(SpawnShip);

...

private void SpawnShip(DiContainer container, float speed)
{
    container.Bind<ShipFacade>().AsSingle();
    container.Bind<Transform>().FromComponentOnRoot();
    var shipPrefab = ships[Random.Range(0, ships.Length)];
    var ship = container.InstantiatePrefab(shipPrefab);
    container.Bind<ShipHealthHandler>().FromNewComponentOn(ship).WhenInjectedInto<ShipFacade>();
    container.BindInstance(speed).WhenInjectedInto<ShipInputHandler>();
}

但这很尴尬,在这种情况下,我想我没有利用子容器的优势。预制件也在一个空的游戏对象中生成。 我想要实现的是能够使用ShipInstaller进行子容器绑定。

你说得对,动态选择子容器预制件并没有非常优雅的方式。

今天我花了一些时间来改进 this commit. If you use the latest version of Extenject 然后你现在可以这样做:

public class QuxInstaller : Installer {
    float _speed;

    public QuxInstaller(float speed) {
        _speed = speed;
    }

    public override void InstallBindings() {
        Container.BindInstance(_speed);
        Container.Bind<QuxFacade>().AsSingle();
    }
}

public class CubeInstaller : MonoInstaller
{
    public List<GameObject> QuxPrefabs;

    public override void InstallBindings()
    {
        Container.BindFactory<float, QuxFacade, QuxFacade.Factory>()
            .FromSubContainerResolve().ByNewPrefabInstaller<QuxInstaller>(ChooseQuxPrefab);
    }

    UnityEngine.Object ChooseQuxPrefab(InjectContext _) {
        return QuxPrefabs[Random.Range(0, QuxPrefabs.Count)];
    }
}