游戏设计中敌人AI状态机:状态是否需自行评估转态逻辑?
敌人AI状态机的典型实现方案探讨
现有脚本结构
基础组件
- Enemy
- EnemyStateManager(状态机管理器)
- EnemyStateBase(状态基类)
状态类
- InitialState(初始状态)
- RoamingState(巡逻状态)
- PursuingState(追击状态)
- AttackingState(攻击状态)
- RetreatingState(撤退状态)
核心疑问
目前不确定应该将敌人的决策逻辑写在状态内部,还是用单独脚本调用当前状态的动作并由状态反馈动作可行性。比如在PursuingState中,敌人需要追逐目标直到进入攻击范围,当前的实现是在UpdateState方法中判断是否进入攻击范围,从而切换到AttackState。
当前实现代码示例
EnemyStateManager(状态机管理器)
public class StateMachine : MonoBehaviour { private EnemyStateBase _currentState; private Enemy _enemy; public Enemy Enemy { get => _enemy; set => _enemy = value; } private void Start() { _currentState = new RoamingState(this); } public void ChangeState(State newState) { _currentState.ExitState(); _currentState = newState; _currentState.EnterState(); } public void Update(){ _currentState.UpdateState(); } }
PursuingState(追击状态)
public class PursuingState : EnemyStateBase { private EnemyStateManager _esm; public PursuingState (EnemyStateManager esm){ _esm = esm; } public override void EnterState() { // 进入追击状态时执行的操作 } public override void UpdateState() { // 检查是否进入目标的攻击范围 var targetPos = _esm.Enemy.Target.Transform.Position; var myPos = _esm.Enemy.Transform.Position; if(Vector3.Distance(myPos, targetPos) < _esm.Enemy.AttackRange){ _esm.ChangeState(new AttackState(_esm)); } } public override void ExitState() { // 退出追击状态时执行的操作 } }
方案分析
你当前的实现方式属于AI状态机的典型方案,和玩家输入驱动的状态机(决策由外部输入触发)不同,AI状态机的核心逻辑就是让状态自身管理决策与状态切换——因为AI的行为逻辑是自主的,不需要外部输入来驱动。
这种将决策逻辑放在状态内部的方式有几个明显优势:
- 职责单一:每个状态只需要关注自身的行为逻辑和切换条件,比如
PursuingState只需要处理追击动作,以及判断何时切换到攻击状态,代码逻辑清晰,易于维护。 - 内聚性强:状态相关的所有逻辑(进入、更新、退出、切换条件)都封装在同一个类中,避免了分散到多个脚本导致的逻辑混乱。
- 扩展性好:后续新增状态时,只需要继承
EnemyStateBase并实现自身的逻辑即可,不需要修改状态机管理器的核心代码,符合开闭原则。
如果采用“单独脚本调用状态动作+状态反馈可行性”的方式,反而会增加不必要的复杂度:需要额外维护一个决策脚本,还要处理状态与决策脚本之间的交互,反而违背了状态机模式封装状态逻辑的初衷。
当然,如果你后续遇到复杂的决策逻辑(比如多个状态共享的判断条件、全局状态切换规则),可以考虑将通用的判断逻辑抽离成工具类或者服务类,供各个状态调用,但核心的状态切换决策依然应该由状态自身来主导。
内容的提问来源于stack exchange,提问作者Katerlad
相关产品推荐
相关产品推荐

