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
相关产品推荐
相关产品推荐

