《艾尔登法环》的低技术 AI 架构
《艾尔登法环》的低技术 AI 架构
《艾尔登法环》之所以能实现惩罚性强且多样化的 NPC 遭遇战,并非通过复杂的规划算法,而是通过一种相对简单的“低技术” AI 架构。该系统主要在 Havok Script(一种面向游戏的 Lua 实现)中实现,并依赖于下推自动机(Pushdown Automaton, PDA)而非传统的有限状态机(Finite State Machine, FSM)或复杂的行为树(Behavior Tree)。
基于目标的下推自动机
《艾尔登法环》的 AI 核心围绕着“目标”(Goal)这一概念展开,目标是 AI 可以占据的唯一状态。与在状态之间转换的标准有限状态机不同,FromSoftware 使用的是目标栈(stack of goals),从而将系统转变为一个下推自动机。
目标栈如何运作
每一帧,Actor 会更新栈顶的目标。执行流遵循以下规则:
- 子目标(Sub-Goals): 一个目标可以向栈中推送(push)新的“子目标”。最顶层的子目标将在下一帧执行。
- 返回值: 目标的更新函数会返回三个值之一:
Continue、Success或Failure。 - 弹出栈:
Success或Failure会导致当前目标从栈中弹出。 - 回溯(Unwinding):
Failure结果会导致栈进行回溯,弹出所有未执行的子目标,直到到达父级目标。
这种结构允许 AI 尝试一系列动作(例如连招攻击),并在该序列的任何部分失败时,优雅地返回到更高层级的决策状态。
通过 Activate Callback 进行决策
核心 AI 逻辑驻留在 activate 回调函数中,当一个目标首次被更新或在耗尽其子目标并恢复执行时,该回调会被触发。
加权随机选择
为了确定下一个动作,AI 通常使用加权随机选择过程。activate 函数会评估当前上下文——例如与玩家的距离以及 Actor 的当前生命值——并为一系列可能的动作分配权重。
例如,如果目标距离较远,则“接近目标”目标的权重会增加;如果目标靠近,则“重击”目标的权重会增加。这些权重还可以通过冷却时间(cooldowns)进一步修改,以防止 AI 频繁使用同一种招式。
通过 Interrupts 实现反应式行为
为了确保 NPC 能立即响应玩家的操作,系统采用了**中断(Interrupt)**机制。中断会从当前执行的目标递归地向其父级“冒泡”,直到中断被“消耗”(即回调函数返回 true)。
这使得某些特定的、“邪恶”的行为成为可能,例如 Bell Bearing Hunter 探测到施法或使用道具后,会立即中止当前动作并发起攻击。中断也可以由动态空间观察区域触发,允许 Boss 在玩家移动到其身后或下方时做出即时反应。
技术实现与数据访问
动画驱动执行
AI 的实际输出大部分是动画驱动的。目标系统会告诉引擎播放特定的动画,而动画事件本身则负责处理碰撞箱(hitbox)时机、弹射物创建以及特效触发。
Actor 数据与内存
与其使用现代 AI 中常见的复杂“黑板”系统,《艾尔登法环》使用的是在每个 Actor 上维护的一个简单的浮点数数组。目标会任意地读取和写入这些索引,以存储和检索状态数据。
中间件集成
FromSoftware 严重依赖 Havok 中间件:
- Havok Script: 用于 AI 逻辑。
- Havok Animation Studio: 用于动画制作。
- Havok Physics: 处理碰撞与物理。
- Havok Navigation: 处理寻路。
与其他 AI 架构的对比
与行为树(BTs)或目标导向动作规划(GOAP)等更“高技术”的替代方案相比,FromSoftware 的方法具有以下优势:
性能: PDA 通常比行为树更快,因为它是从栈顶执行单个目标,而不是每一帧都从根节点重新评估整个复杂的树状节点结构。
简单性: 通过在状态内使用命令式代码来处理控制流,FromSoftware 避免了大型行为树或有限状态机中常见的“节点爆炸”问题。
设计师控制力: 该系统将动作序列牢牢掌握在战斗设计师和动画师手中,而非将序列委派给搜索算法(如 GOAP 或 STRIPS)。
“如果使用这种结构(基于通用的脚本语言)进行为期一个‘周末’的实现,基本上足以实现像《艾尔登法环》如此规模的游戏。”
社区洞察
虽然作者将该系统描述为“低技术”,但社区中的一些开发者认为,复杂性在于单个目标的实现(例如,成功执行“攻击”目标所需的物理和 3D 空间检查)以及关卡设计。一位评论者指出,敌人智能的表现往往是巧妙的关卡设计和仇恨管理(aggro management)的结果,而非 AI 逻辑本身。