10.Unity Zenject高级编程(使用工厂动态创建物体)


前言

新手使用Zenject框架经常会遇到一个头痛的问题,怎么样在游戏启动以后动态创建新物体;
假如你做一个游戏需要生成很多的敌人(Enemies),然后你将会去构建新的敌人实类,
并且要确保这些敌人实类会注入到框架里面,建议使用工厂来处理


摘要

DI框架重要的部分是储备使用容器,严格的遵循"Composition Root Layer"组合跟节点层;
DiContainer容器类包括自身的自动引用,因此将无法阻止你忽略这个规则并且注入容器任意你想要的类,代码示例:

public class Enemy
{
   
    DiContainer Container;

    public Enemy(DiContainer container)
    {
   
        Container = container;
    }

    public void Update()
    {
   
        ...
        var player = Container.Resolve<Player>();
        WalkTowards(player.Position);
        ...
        etc.
    }
}

然而,上面的代码是一个反面例子,可以正常运行,你可以使用Container访问游戏里面其他的类,
如果你这样做的话,严格意义上来说,这不是DI框架的魅力所在;
当然,你可以这样编写代码:

public class Enemy
{
   
    Player _player;

    public Enemy(Player player)
    {
   
        _player = player;
    }

    public void Update()
    {
   
        ...
        WalkTowards(_player.Position);
        ...
    }
}

但现在,每一个创建新Enemy的地方需要补充一个Player的实例,这样违背了软件设计原则的开闭原则,
当使用工厂来处理以后,Zenject会自动补充另外需要的实类

代码示例
public class Player
{
   
}

public class Enemy
{
   
    readonly Player _player;

    public Enemy(Player player)
    {
   
        _player = player;
    }

    public class Factory : PlaceholderFactory<Enemy>
    {
   
    }
}

public class EnemySpawner : ITickable
{
   
    readonly Enemy.Factory _enemyFactory;

    public EnemySpawner(Enemy.Factory enemyFactory)
    {
   
        _enemyFactory = enemyFactory;
    }

    public void Tick()
    {
   
        if (ShouldSpawnNewEnemy())
        {
   
            var enemy = _enemyFactory.Create();
            // ...
        }
    }
}

public class TestInstaller : MonoInstaller
{
   
    public override void InstallBindings()
    {
   
        Container.BindInterfacesTo<EnemySpawner>().AsSingle();
        Container.Bind<Player>().AsSingle();
        Container.BindFactory<Enemy, Enemy.Factory>();
    }
}

通过使用Ememy.Factory来替代new Enemy,所有的敌人引用类,类如Player类会自动填充;
我们也可以给工厂添加参数,代码示例:

public class Enemy
{
   
    readonly Player _player;
    readonly float _speed;

    public Enemy(float speed, Player player)
    {
   
        _player = player;
        _speed = speed;
    }

    public class Factory : PlaceholderFactory<float, Enemy>
    {
   
    }
}

public class EnemySpawner : ITickable
{
   
    readonly Enemy.Factory _enemyFactory;

    public EnemySpawner(Enemy.Factory enemyFactory)
    {
   
        _enemyFactory = enemyFactory;
    }

    public void Tick()
    {
   
        if (ShouldSpawnNewEnemy())
        {
   
            var newSpeed = Random.Range(MIN_ENEMY_SPEED, MAX_ENEMY_SPEED);
            var enemy = _enemyFactory.Create(newSpeed)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值