个人游戏技术选型案例:敌人 AI 为什么选择有限状态机而不是行为树

一个个人潜行动作游戏在有限状态机、行为树和 GOAP 之间做敌人 AI 技术选型的案例,详细讨论可调试性、关卡脚本、警戒状态和个人开发维护成本。

写在前面:AI 看起来聪明,不等于系统应该复杂

个人游戏做敌人 AI 时,很容易被复杂方案吸引。

行为树、GOAP、Utility AI、黑板系统、感知组件、记忆系统。
这些方案都很有用,也确实支撑了很多商业游戏。

但技术选型不是看方案名字是否高级。
它要看游戏实际需要多少行为复杂度,以及开发者能否长期调试和维护。

韩序做过一款俯视角潜行动作游戏。
玩家扮演一名夜间档案员,在封锁的市政楼里躲避巡逻保安、关闭摄像头、偷取文件。

游戏需要敌人有警戒、搜索、巡逻、呼叫同伴等行为。
他最初准备使用行为树,甚至买了一个可视化插件。

两周原型后,他改成了有限状态机加少量行为模块。

这个选择让 AI 没那么“学术”,但更容易调试,也更适合他的关卡规模。

一、先定义敌人真的要做什么

韩序没有从 AI 框架开始。

他先列出敌人的实际行为:

  • 按路径巡逻
  • 听到声音后走向声音来源
  • 看到玩家后追击
  • 失去视野后搜索最后位置
  • 搜索失败后回到巡逻
  • 发现门被打开后短暂警戒
  • 发现同伴倒地后呼叫警报
  • 被闪光灯干扰后停顿

这些行为看起来不少,但结构很清楚。

敌人并不需要复杂规划。
他们不会自己制定长期目标,不会自由使用道具,也不会在大型开放场景里动态协作。

这说明 GOAP 之类的规划系统可能过重。

二、行为树原型遇到的问题

行为树原型一开始很好用。

韩序做了几个节点:

  • 是否看到玩家
  • 是否听到声音
  • 是否处于警戒
  • 追击
  • 搜索
  • 巡逻
  • 等待

但当关卡脚本和特殊敌人加入后,树变得越来越难读。

比如某个二层保安:

  • 先巡逻
  • 看到玩家后不能直接追,要先去按警铃
  • 如果警铃被玩家提前破坏,才呼叫同伴
  • 如果同伴已倒地,则进入恐慌搜索

这些逻辑可以写进行为树,但树很快膨胀。

更麻烦的是调试。

玩家反馈“保安有时看到我但不追”。
韩序要在行为树节点、黑板变量、感知回调和动画状态之间查原因。

对个人开发者来说,调试成本比架构弹性更现实。

三、有限状态机的优势

韩序改成了有限状态机。

核心状态只有几个:

  • Patrol
  • Investigate
  • Chase
  • Search
  • Alert
  • Stunned
  • Return

每个状态有明确入口、更新和退出逻辑。
状态切换集中记录。

例如:

  • Patrol -> Investigate:听到声音
  • Patrol -> Chase:看到玩家
  • Chase -> Search:失去视野
  • Search -> Return:搜索计时结束
  • Any -> Stunned:被闪光灯命中

这让问题可见。

当敌人行为异常时,他可以直接看日志:

Patrol -> Investigate -> Chase -> Search

如果没有进入 Chase,说明感知没有触发。
如果进入后马上退出,说明视野或路径条件有问题。

状态机不一定比行为树强。
但它在这个项目里更透明。

四、行为模块避免状态爆炸

纯状态机也有风险。

如果把每种特殊行为都写成新状态,很快会出现:

  • PatrolWithRadio
  • SearchAfterAlarm
  • ChaseButNoDoor
  • InvestigateBrokenCamera

状态数量会爆炸。

韩序用行为模块处理变化。

状态机负责高层行为。
模块负责可替换能力:

  • VisionSensor
  • HearingSensor
  • PatrolRoute
  • AlarmResponder
  • DoorPolicy
  • SearchPattern

普通保安和队长都使用同一套状态机。
差异来自模块配置。

队长的 AlarmResponder 会先呼叫同伴。
普通保安只会跑向警铃。
老保安的 SearchPattern 更短,搜索一会儿就返回。

这样既保留状态机清晰度,又避免每种敌人写一套逻辑。

五、感知系统要独立于状态

韩序早期把视野检测写在状态里。

巡逻状态检测玩家,追击状态也检测玩家,搜索状态还要检测玩家。
重复逻辑越来越多。

后来他把感知独立出来。

VisionSensorHearingSensor 只负责产生事件:

  • PlayerSeen
  • PlayerLost
  • NoiseHeard
  • BodyFound
  • SuspiciousDoorFound

状态机决定如何响应这些事件。

这让感知系统可以统一调试。
也方便关卡工具显示敌人视野、听觉范围和最后感知位置。

个人游戏里,AI 最容易混乱的地方就是“看见”和“决定”混在一起。
把感知和决策分开,很多 bug 会清楚很多。

六、关卡脚本怎么接入

潜行游戏常有特殊事件。

例如:

  • 玩家偷到文件后,所有保安巡逻路线改变
  • 某个房间断电后,附近保安进入调查
  • 警报响起后,出口保安不再离岗

韩序没有让关卡脚本直接改敌人内部状态。

它只发送高层指令:

  • SetAlertLevel(2)
  • LockRoute("exit_guard")
  • BroadcastNoise(position, intensity)
  • DisableCameraGroup("floor_2")

敌人根据自己的状态和模块响应。

这样关卡脚本不会变成 AI 的隐藏控制器。

如果关卡脚本到处写“把敌人切到 Chase”,后期会很难维护。

七、可视化调试比复杂 AI 更重要

韩序花时间做了一个调试面板。

它显示:

  • 当前状态
  • 上一个状态
  • 当前目标点
  • 是否看到玩家
  • 最后听到声音位置
  • 警戒等级
  • 巡逻路线
  • 搜索剩余时间

在编辑器里,还能显示视野扇形和听觉半径。

这个工具比换更高级 AI 框架更有用。

因为 AI 问题最难的是不知道它为什么这样做。
只要原因可见,很多行为都能快速调整。

八、最终取舍

韩序的最终方案是:

  • 高层使用有限状态机
  • 感知系统独立
  • 差异行为用模块配置
  • 关卡脚本只发高层事件
  • 做可视化调试面板
  • 不使用 GOAP
  • 暂不使用完整行为树

这个方案没有行为树灵活,也不适合大型开放世界 NPC。

但它足够支撑 8 到 10 种敌人和 20 多个手工关卡。

最重要的是,韩序一个人能理解和调试。

结语:AI 技术选型要看调试成本

韩序后来总结,敌人 AI 不需要让开发者觉得聪明。
它需要让玩家觉得公平、可信、可预期。

对个人游戏来说,AI 系统最重要的不是抽象能力,而是:

  • 行为能解释
  • bug 能复现
  • 关卡能控制
  • 特殊敌人能配置
  • 半年后还能看懂

如果有限状态机已经能做到这些,就没有必要为了“更高级”提前引入行为树或规划系统。

聪明的 AI,不一定来自复杂框架。
有时来自清楚的状态、稳定的感知和可调试的工具。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页