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

游戏AI状态机:基类虚方法能否中止子类重写方法的执行?

游戏AI状态机:高优先级状态切换的执行终止方案

问题背景

在游戏AI状态机实现中,EatState是优先级最高的状态,可从多数状态直接切换至该状态。为避免重复定义切换逻辑,计划在所有状态的父类BaseState中统一实现该逻辑。BaseState包含4个需子类重写的抽象方法:

  • Enter()
  • UpdateLogic():负责检查状态切换条件
  • UpdatePhysics():处理移动等物理操作
  • Exit()

当前实现存在逻辑覆盖问题:基类UpdateLogic中实现了EatState的切换检查,但子类重写时调用base.UpdateLogic()后,自身的切换条件若满足会覆盖基类的状态切换结果,导致高优先级的EatState被低优先级状态顶替,示例代码如下:

public class BaseState {
   public virtual void UpdateLogic() {
      // 假设条件满足,切换至EatState
      if (someCondition){
         changeState("EatState");
      }
   }
}

public class MoveState : BaseState {
   public override void UpdateLogic() {
      base.UpdateLogic();
      // 此处条件满足时,状态会被重新切换为FightState,覆盖基类的结果
      if (someOtherCondition){
         changeState("FightState");
      }
   }
}

核心问题解决方案

要实现基类虚方法执行时中止子类重写方法的后续执行,可通过以下三种方案实现:

1. 基于返回值的流程控制

修改基类UpdateLogic的返回值为布尔类型,用于标记是否已触发高优先级状态切换,子类根据返回值决定是否继续执行自身逻辑:

public class BaseState {
    public virtual bool UpdateLogic() {
        // 检查EatState切换条件
        if (someCondition) {
            changeState("EatState");
            return true; // 返回true表示已触发高优先级切换,子类无需继续执行
        }
        return false; // 未触发切换,子类可执行自身逻辑
    }
}

public class MoveState : BaseState {
    public override bool UpdateLogic() {
        bool hasSwitchedToHighPriority = base.UpdateLogic();
        if (hasSwitchedToHighPriority) {
            return true; // 基类已完成高优先级切换,直接终止后续逻辑
        }
        // 子类自身的状态切换逻辑
        if (someOtherCondition) {
            changeState("FightState");
            return true;
        }
        return false;
    }
}

该方案需要子类遵守约定,主动检查基类的返回值来控制流程。

2. 基于状态标记的流程控制

在BaseState中添加受保护的状态标记字段,基类触发切换时设置标记,子类执行自身逻辑前检查该标记:

public class BaseState {
    protected bool _hasSwitchedState = false;

    public virtual void UpdateLogic() {
        _hasSwitchedState = false;
        if (someCondition) {
            changeState("EatState");
            _hasSwitchedState = true;
        }
    }
}

public class MoveState : BaseState {
    public override void UpdateLogic() {
        base.UpdateLogic();
        if (_hasSwitchedState) {
            return; // 基类已切换状态,终止后续执行
        }
        if (someOtherCondition) {
            changeState("FightState");
        }
    }
}

该方案通过标记传递状态信息,同样需要子类主动检查标记以终止执行。

3. 模板方法模式重构(推荐)

将UpdateLogic拆分为基类控制的固定流程和子类实现的自定义逻辑部分,基类先执行高优先级状态检查,仅当未触发切换时才调用子类的自定义逻辑:

public abstract class BaseState {
    public void UpdateLogic() {
        // 优先执行高优先级状态检查
        if (CheckHighPriorityStates()) {
            return; // 已切换高优先级状态,直接终止流程
        }
        // 未触发高优先级切换,执行子类自定义逻辑
        CheckCustomStates();
    }

    // 基类实现高优先级状态检查(如EatState)
    protected virtual bool CheckHighPriorityStates() {
        if (someCondition) {
            changeState("EatState");
            return true;
        }
        return false;
    }

    // 子类重写该方法实现自身的状态切换逻辑
    protected abstract void CheckCustomStates();

    // 实现其他抽象方法
    public abstract void Enter();
    public abstract void UpdatePhysics();
    public abstract void Exit();
}

public class MoveState : BaseState {
    protected override void CheckCustomStates() {
        if (someOtherCondition) {
            changeState("FightState");
        }
    }

    // 实现其他抽象方法
    public override void Enter() { /* ... */ }
    public override void UpdatePhysics() { /* ... */ }
    public override void Exit() { /* ... */ }
}

该方案从架构层面固定了执行顺序,子类无需关心高优先级状态的逻辑,彻底避免了人为失误导致的逻辑覆盖问题,是最健壮的实现方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 11:48:28