写在前面:AI 看起来聪明,不等于系统应该复杂
个人游戏做敌人 AI 时,很容易被复杂方案吸引。
行为树、GOAP、Utility AI、黑板系统、感知组件、记忆系统。
这些方案都很有用,也确实支撑了很多商业游戏。
但技术选型不是看方案名字是否高级。
它要看游戏实际需要多少行为复杂度,以及开发者能否长期调试和维护。
韩序做过一款俯视角潜行动作游戏。
玩家扮演一名夜间档案员,在封锁的市政楼里躲避巡逻保安、关闭摄像头、偷取文件。
游戏需要敌人有警戒、搜索、巡逻、呼叫同伴等行为。
他最初准备使用行为树,甚至买了一个可视化插件。
两周原型后,他改成了有限状态机加少量行为模块。
这个选择让 AI 没那么“学术”,但更容易调试,也更适合他的关卡规模。
一、先定义敌人真的要做什么
韩序没有从 AI 框架开始。
他先列出敌人的实际行为:
- 按路径巡逻
- 听到声音后走向声音来源
- 看到玩家后追击
- 失去视野后搜索最后位置
- 搜索失败后回到巡逻
- 发现门被打开后短暂警戒
- 发现同伴倒地后呼叫警报
- 被闪光灯干扰后停顿
这些行为看起来不少,但结构很清楚。
敌人并不需要复杂规划。
他们不会自己制定长期目标,不会自由使用道具,也不会在大型开放场景里动态协作。
这说明 GOAP 之类的规划系统可能过重。
二、行为树原型遇到的问题
行为树原型一开始很好用。
韩序做了几个节点:
- 是否看到玩家
- 是否听到声音
- 是否处于警戒
- 追击
- 搜索
- 巡逻
- 等待
但当关卡脚本和特殊敌人加入后,树变得越来越难读。
比如某个二层保安:
- 先巡逻
- 看到玩家后不能直接追,要先去按警铃
- 如果警铃被玩家提前破坏,才呼叫同伴
- 如果同伴已倒地,则进入恐慌搜索
这些逻辑可以写进行为树,但树很快膨胀。
更麻烦的是调试。
玩家反馈“保安有时看到我但不追”。
韩序要在行为树节点、黑板变量、感知回调和动画状态之间查原因。
对个人开发者来说,调试成本比架构弹性更现实。
三、有限状态机的优势
韩序改成了有限状态机。
核心状态只有几个:
PatrolInvestigateChaseSearchAlertStunnedReturn
每个状态有明确入口、更新和退出逻辑。
状态切换集中记录。
例如:
Patrol -> Investigate:听到声音Patrol -> Chase:看到玩家Chase -> Search:失去视野Search -> Return:搜索计时结束Any -> Stunned:被闪光灯命中
这让问题可见。
当敌人行为异常时,他可以直接看日志:
Patrol -> Investigate -> Chase -> Search
如果没有进入 Chase,说明感知没有触发。
如果进入后马上退出,说明视野或路径条件有问题。
状态机不一定比行为树强。
但它在这个项目里更透明。
四、行为模块避免状态爆炸
纯状态机也有风险。
如果把每种特殊行为都写成新状态,很快会出现:
PatrolWithRadioSearchAfterAlarmChaseButNoDoorInvestigateBrokenCamera
状态数量会爆炸。
韩序用行为模块处理变化。
状态机负责高层行为。
模块负责可替换能力:
VisionSensorHearingSensorPatrolRouteAlarmResponderDoorPolicySearchPattern
普通保安和队长都使用同一套状态机。
差异来自模块配置。
队长的 AlarmResponder 会先呼叫同伴。
普通保安只会跑向警铃。
老保安的 SearchPattern 更短,搜索一会儿就返回。
这样既保留状态机清晰度,又避免每种敌人写一套逻辑。
五、感知系统要独立于状态
韩序早期把视野检测写在状态里。
巡逻状态检测玩家,追击状态也检测玩家,搜索状态还要检测玩家。
重复逻辑越来越多。
后来他把感知独立出来。
VisionSensor 和 HearingSensor 只负责产生事件:
PlayerSeenPlayerLostNoiseHeardBodyFoundSuspiciousDoorFound
状态机决定如何响应这些事件。
这让感知系统可以统一调试。
也方便关卡工具显示敌人视野、听觉范围和最后感知位置。
个人游戏里,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,不一定来自复杂框架。
有时来自清楚的状态、稳定的感知和可调试的工具。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。