第二部分:敌人功能——状态机优化

        PS:之前完成的敌人状态机:状态机实现 。

        一:旧版状态机

                在之前的状态机实现中,我们主要做了状态类(StateActionSO ),转换器类(TransitionSO ),转换条件类(ConditionSO ),将它们解耦合并且进行了复用。

                但是每一个敌人对象都要挂载一个StateMachine的脚本,这显然是不想看到的。

        二:新版状态机

                针对这个问题,通过采用接口 + 观察者模式一管理所有敌人的方式来改进。

        (1)接口:主要提供 注册 和 注销 的方法

public interface IStateMachineEnemy
{
    public void RegisterStateMachineEnemy();

    public void UnRegisterStateMachineEnemy();
}

        (2)新的状态机:抽象基类 + 泛型。将其设置为单例(方便注册敌人,也可以采取别的更好方式),并且将泛型限制为EnemyController的子类。我们可以为每种类型的敌人创建一个具体状态机的子类,并且挂载在一个长久存在的对象上,同时设置它的转换器以及初始状态。

        进一步地,我们可以在子类的状态机中根据具体敌人的特殊性进行扩展和修改。此外,由于不是每个敌人都挂载StateMachine,因此要将StateActionSO ,TransitionSO ,ConditionSO 的所有函数参数直接变更为敌人EnemyController类型即可。

        这样的话,在敌人的控制器中,只需要维护一个CurrentEnemyState的属性即可,在一定程度上进行了解耦合。同时将同种类型的敌人进行统一的处理,也符合局部性原则。

注:实际上将全部敌人不分种类统一管理也可以,只通过状态,转换器,转换条件来约束敌人。

public abstract class StateMachine<T> : Singleton<StateMachine<T>> where T : EnemyController
{
    [SerializeField] private TransitionSO transition;

    [SerializeField] private StateActionSO initState;

    private List<T> enemies = new();
    

    private void Update()
    {
        for (int i = 0; i < enemies.Count; i++)
        {
            StateMachineTick(enemies[i]);
        }
    }

    private void StateMachineTick(EnemyController enemy)
    {
        if (transition != null) transition.TryGetApplyCondition(enemy); //每一帧都去找是否有成立的条件

        if (CanEnemyAction(enemy))
            if (enemy.CurrentEnemyState != null)
                enemy.CurrentEnemyState.OnUpdate(enemy);
    }

    //敌人是否能行动的条件判断
    protected virtual bool CanEnemyAction(EnemyController enemy)
    {
        if (enemy == null || enemy.IsDead || enemy.IsHurt || enemy.enemyCharacterStats.IsWeakState ||
            enemy.IsExecuted) return false;
        return true;
    }

    #region 添加删除敌人的接口

    public void AddEnemy(T enemy)
    {
        enemies.Add(enemy);
        StartCoroutine(InitEnemyState(enemy));
    }

    public void RemoveEnemy(T enemy)
    {
        enemies.Remove(enemy);
    }

    private IEnumerator  InitEnemyState(T enemy)
    {
        yield return null;
        if (enemy != null && CanEnemyAction(enemy))
        {
            enemy.CurrentEnemyState = initState;
            enemy.CurrentEnemyState.OnEnter(enemy);
        }
    }
    

    #endregion
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值