You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity3D中基于Zenject实现带子容器与实例化参数的自定义工厂

在Unity+Zenject中实现带参数的自定义工厂并控制暴露范围

针对你的需求,这里提供一套完整的实现方案,分四步解决参数传递和访问控制的问题:

1. 定义自定义工厂接口

首先创建工厂接口,明确实例化时需要传递的参数:

public interface IPlayerFactory
{
    PlayerFacade Create(Transform parent = null, Vector3 position = default, Quaternion rotation = default);
}

2. 实现工厂逻辑

编写工厂类,依赖Zenject容器和Player预制体,在实例化时处理位置、旋转和父物体设置,同时仅返回对外暴露的PlayerFacade:

public class PlayerFactory : IPlayerFactory
{
    private readonly DiContainer _container;
    private readonly GameObject _playerPrefab;

    // 通过构造注入获取容器和预制体
    public PlayerFactory(DiContainer container, GameObject playerPrefab)
    {
        _container = container;
        _playerPrefab = playerPrefab;
    }

    public PlayerFacade Create(Transform parent = null, Vector3 position = default, Quaternion rotation = default)
    {
        // 实例化预制体,同时传递父物体、位置、旋转参数
        var playerInstance = _container.InstantiatePrefab(
            _playerPrefab, 
            position, 
            rotation, 
            parent);

        // 从实例中获取对外暴露的Facade(内部对象不会被场景容器访问到)
        return playerInstance.GetComponent<PlayerFacade>();
    }
}

3. 配置PlayerInstaller(GameObject上下文)

在Player预制体的PlayerInstaller中,仅将PlayerFacade绑定为对外可见的类型,内部依赖(如PlayerEntity、PlayerView)仅在子容器内绑定,不对外暴露:

public class PlayerInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        // 绑定内部核心对象,仅在当前GameObject上下文可见
        Container.Bind<PlayerEntity>().AsSingle();
        Container.Bind<PlayerView>().FromComponentOnRoot().AsSingle();
        // 其他内部服务同理,只在子容器内绑定,不向外暴露

        // 仅对外暴露PlayerFacade,场景上下文只能通过这个类访问玩家功能
        Container.Bind<PlayerFacade>().FromComponentOnRoot().AsSingle();
    }
}

4. 配置SceneInstaller(场景上下文)

在场景的SceneInstaller中,绑定工厂并关联Player预制体,确保工厂能被其他场景对象注入使用:

public class SceneInstaller : MonoInstaller
{
    [SerializeField] private GameObject _playerPrefab; // 拖拽Player预制体到这里

    public override void InstallBindings()
    {
        // 绑定自定义工厂
        Container.Bind<IPlayerFactory>().To<PlayerFactory>().AsSingle();
        // 将Player预制体注入到工厂中
        Container.BindInstance(_playerPrefab);
    }
}

使用示例

在任何需要创建玩家的场景对象中,注入IPlayerFactory即可调用:

public class GameManager : MonoBehaviour
{
    [Inject] private IPlayerFactory _playerFactory;

    public void SpawnPlayer()
    {
        // 传入位置、旋转和父物体创建玩家
        var playerFacade = _playerFactory.Create(
            parent: transform,
            position: new Vector3(0, 1, 0),
            rotation: Quaternion.identity);
        
        // 仅能通过PlayerFacade调用对外暴露的方法,内部对象无法访问
        playerFacade.InitializePlayer();
    }
}

关键说明

  • 由于Player预制体的GameObject上下文是独立子容器,PlayerInstaller中绑定的PlayerEntity等内部对象仅存在于子容器中,场景容器无法直接获取,完全满足“仅暴露PlayerFacade”的要求。
  • 自定义工厂通过DiContainer.InstantiatePrefab()方法实现参数传递,替代InstantiatePrefabForComponent,同时直接获取Facade对象;如果需要对外提供PlayerEntity的功能,可在PlayerFacade内部持有PlayerEntity引用并暴露对应的方法。

内容的提问来源于stack exchange,提问作者Evgenii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:11:13