约 14 分钟技术学习游戏引擎

Games104学习笔记(20)

GAMES104:游戏引擎 Gameplay 玩法系统:高级 AI(上)

课程:GAMES104《现代游戏引擎:从入门到实践》
第 17 讲(上):游戏引擎 Gameplay 玩法系统:高级 AI
本地视频时长:约 1 小时 47 分钟

一、从反应式 AI 到规划式 AI

有限状态机和行为树擅长按照预先设计的结构响应环境,但复杂任务常包含多种完成方式,且执行条件会随玩家行为变化。此时,把所有可能分支预先写进状态或树结构,会使逻辑快速膨胀。

规划式 AI 的思路是:设计者提供目标、动作、约束和世界状态,规划器在运行时或离线阶段组合出行动序列。它不再只回答“当前执行哪一个节点”,而是回答“为了实现目标,接下来应该依次做什么”。

本讲主要介绍三类方法:

方法 核心思想 典型用途
HTN 将高层任务逐步分解为可执行的基础任务 结构明确、带领域经验的长程行为
GOAP 在状态与动作构成的图上搜索低成本计划 目标明确、动作组合需要动态变化的 AI
MCTS 用大量模拟逐步扩展高价值决策分支 状态空间巨大、适合前瞻博弈的决策

二、学习目标

  • 理解世界状态、目标、动作、计划和执行器之间的关系。
  • 掌握 HTN 的任务层级、方法选择、规划与重规划流程。
  • 掌握 GOAP 的目标集、动作前置条件、效果和代价模型。
  • 理解 MCTS 的选择、扩展、模拟、回传以及探索—利用平衡。
  • 比较三类规划方法的优势、成本与适用边界。

三、规划系统的通用结构

规划方法虽然不同,但通常都依赖以下元素:

元素 作用
Sensors 从游戏世界提取 AI 可知的信息
World State 表示 AI 当前认知到的世界状态
Goals 或 Root Task 定义 AI 想实现的结果
Actions 或 Tasks 表示可以执行的行为及其条件
Planner 搜索或分解得到行动序列
Plan Runner 执行计划并跟踪结果

世界状态是 AI 的主观模型,不必等同于游戏的完整真实状态。它可能包含“看到敌人”“拥有药水”“生命值较低”“出口已知”等有限属性。感知系统更新这些属性,规划器只在这个抽象空间中推理。

规划系统的质量高度依赖抽象:状态过少,计划无法区分关键情形;状态过细,搜索空间和维护成本会急剧上升。

四、HTN:按层级分解任务

1. 基本思想

HTN,即 Hierarchical Task Network,把复杂目标表示为层级任务。高层任务不能直接执行,需要通过某种方法分解为更小的子任务,直到得到一串可执行的基础任务。

例如“生存”可以分解为:

  • 有药水时:使用药水。
  • 有材料时:制作药水,再使用药水。
  • 有金币时:购买药水,再使用药水。
  • 条件都不满足时:逃跑或寻找资源。

设计者不是直接写死唯一行动序列,而是为同一个任务提供多种分解方法,并为每种方法定义适用条件。

2. HTN 的组成

HTN 框架通常由四部分构成:

组成 内容
World State AI 已知的属性和状态
HTN Domain 任务层级、分解方法与前置条件
Planner 根据当前状态选择方法并生成计划
Plan Runner 按顺序执行基础任务并更新状态

感知系统负责把游戏世界转化为 World State;Domain 保存设计者的领域知识;Planner 负责组合任务;Runner 则把计划落到实际 Gameplay 系统。

3. 基础任务

基础任务是可以直接执行的行为,例如移动到指定位置、使用物品、攻击敌人或播放交互。

一个基础任务通常包含:

  • 前置条件:当前是否允许执行。
  • 操作:真正调用的行为。
  • 效果:成功后世界状态如何改变。
  • 成败结果:供计划执行器决定是否继续。

基础任务应尽量稳定、粒度清晰。若一个基础任务内部又隐藏大量决策,它实际上仍是一个复合任务,会削弱规划器的可见性。

4. 复合任务与方法

复合任务不能直接执行,而是包含多个候选方法。每个方法由前置条件和一串子任务组成,并可具有优先级。

规划时,系统按规则寻找第一个满足条件的方法,把它展开为子任务;若子任务仍是复合任务,则继续递归分解。最终输出一串基础任务。

这种结构把设计者经验编码为“当环境满足某条件时,可用哪种解决方案”。它能生成长程、可解释的计划,也比纯状态机更容易复用高层行为。

5. HTN 规划过程

规划器通常在临时状态副本上进行分解:

  1. 从根任务开始。
  2. 检查复合任务的候选方法。
  3. 选择前置条件满足的方法。
  4. 递归展开子任务。
  5. 遇到基础任务时,验证其前置条件。
  6. 假设任务成功,并把效果写入临时世界状态。
  7. 所有任务成功展开后,得到最终计划。

临时状态的作用是让后续任务看到前面任务的预期效果。例如“制作药水”会在临时状态中增加药水数量,使后续“使用药水”的前置条件能够成立。

若某个基础任务条件不满足,规划器需要回退并尝试其他方法。若所有候选方法都失败,则整个规划失败。

6. 执行与重规划

计划生成后由 Runner 顺序执行。现实游戏环境并不会严格按照规划预测发展:玩家可能抢走资源,目标可能死亡,出口可能被封锁。因此系统需要在以下情况重新规划:

  • 当前没有计划。
  • 当前计划已完成。
  • 某个任务执行失败。
  • 感知到的世界状态发生关键变化。

重规划频率过低会让 AI 固执执行失效计划,过高则会浪费计算,并导致角色频繁改变意图。工程中通常根据关键状态变化触发,并辅以冷却和优先级。

7. HTN 的优势与局限

优势:

  • 层级结构适合表达长程任务。
  • 计划结果清晰,便于调试和解释。
  • 领域知识可直接编码到任务分解中。
  • 规划成本通常比在完全自由的动作空间中搜索更低。

局限:

  • Domain 需要设计者预先组织大量任务与方法。
  • 玩家行为不可预测时,计划容易失效。
  • 世界状态和任务效果的抽象很难一次设计正确。
  • 过强的层级约束可能限制 AI 产生新组合。

五、GOAP:围绕目标搜索动作序列

1. 基本思想

GOAP,即 Goal-Oriented Action Planning,不要求设计者直接给出任务分解树,而是定义目标和一组动作。规划器根据当前状态,搜索一串能把世界变成目标状态的动作。

整体流程是:

  1. 从 Goal Set 中选择当前最重要且尚未满足的目标。
  2. 在 Action Set 中搜索能够实现该目标的动作序列。
  3. 执行计划。
  4. 当环境变化或计划失败时重新选择目标并规划。

2. 目标集

一个目标通常包含:

  • 目标前置条件:何时该目标可以被考虑。
  • 目标状态:完成后希望哪些世界状态成立。
  • 优先级:多个目标同时可用时如何选择。

例如“恢复生命”“消除威胁”“保护队友”“巡逻”等目标可以同时存在,但 AI 会根据当前生命值、敌人状态和任务要求选择优先目标。

目标优先级可以是固定值,也可以根据世界状态动态变化。动态优先级更灵活,但必须防止两个目标在相近分值间来回切换。

3. 动作集

一个 GOAP 动作可以表示为:

$$ a = \left(P_a, E_a, C_a\right) $$

其中 $P_a$ 是前置条件,$E_a$ 是执行后的效果,$C_a$ 是动作代价。

例如“购买药水”的前置条件是拥有足够金币并能到达商店;效果是药水数量增加、金币减少;代价可以包含时间、距离、风险或资源消耗。

4. 将规划转成图搜索

世界状态的不同组合可视为图节点,动作是连接状态的边,动作代价是边权重。规划问题因而可以转化为从当前状态到目标状态的低成本路径搜索。

若当前状态为 $s_0$,目标条件为 $G$,行动序列为 $\pi=(a_1,a_2,\ldots,a_k)$,规划器希望找到满足目标且总代价较低的序列:

$$ \pi^* = \arg\min_{\pi}\sum_{i=1}^{k} C_{a_i} $$

搜索可以从当前状态正向应用动作,也可以从目标状态反向寻找能产生所需效果的动作。后者常能减少与目标无关的候选动作。

5. GOAP 的优势与局限

优势:

  • 目标与具体行为解耦,同一目标可以产生不同计划。
  • 新增动作后,现有目标可能自动获得新的实现方式。
  • 比 HTN 更容易产生设计者没有显式列出的动作组合。
  • 代价函数可让 AI 在时间、风险和资源之间权衡。

局限:

  • 运行时搜索通常比 HTN 分解更慢。
  • 状态、动作前置条件和效果难以完整、准确地建模。
  • 动作数量与状态维度增大后,搜索空间迅速膨胀。
  • 抽象模型与真实执行不一致时,计划会频繁失败。

六、HTN 与 GOAP 的对比

维度 HTN GOAP
主要输入 层级任务与分解方法 目标、动作、前置条件、效果与代价
计划来源 递归分解高层任务 在状态—动作空间中搜索
设计者控制 强,计划结构较可预测 较弱,动作组合更动态
运行时成本 通常较低 通常较高
可解释性 高,任务层级清晰 较高,可查看目标和动作序列
主要风险 Domain 编写繁重、限制新组合 状态空间膨胀、模型容易不一致

HTN 更像把专家经验组织成层级配方;GOAP 更像给出目标和工具,让规划器自行寻找一条可行路径。实际项目可以组合两者:高层用 HTN 约束战略结构,局部任务内部再用 GOAP 搜索行动。

七、MCTS:在巨大决策空间中做前瞻搜索

1. 为什么需要采样式搜索

围棋等问题的完整状态空间极其庞大,无法穷举所有行动序列。蒙特卡洛树搜索通过反复模拟,把计算集中到更有希望的分支,在有限预算内逐步改善决策质量。

在搜索树中:

  • 节点表示游戏状态。
  • 边表示一次动作。
  • 从根到节点的路径表示一串行动。

MCTS 不要求一次构造完整搜索树,而是边采样、边统计、边扩展。

2. 四个基本阶段

每轮 MCTS 通常包含四个阶段:

  1. Selection:从根节点沿选择策略向下,找到可扩展节点。
  2. Expansion:选择一个未尝试动作,创建新的子节点。
  3. Simulation:从新节点出发,按照默认策略快速模拟到终局或截断条件。
  4. Backpropagation:将模拟结果沿访问路径反向更新到各祖先节点。

重复足够多轮后,访问次数和平均收益会逐渐反映各分支的潜力。

3. 默认策略

模拟阶段需要一个能够快速行动的默认策略。最简单的是随机行动,但完全随机可能产生大量低质量样本。也可以使用简单规则、启发式或轻量模型,使模拟结果更接近合理玩法。

默认策略不必达到最终 AI 的水平,它的重点是成本低、覆盖广,并能提供有区分度的结果。

4. 回传

模拟完成后,结果沿当前路径回传。每个经过的节点更新访问次数与累计收益,例如:

  • 胜利记为 $1$。
  • 失败记为 $0$ 或 $-1$。
  • 平局记为中间值。

不同玩家轮流行动时,还需要从当前节点所属玩家的视角处理收益符号,否则搜索会错误地假设双方都在帮助同一个玩家。

5. 探索与利用

选择阶段面临两个目标:

  • 利用:继续搜索当前平均收益较高的分支。
  • 探索:尝试访问次数少、结果仍不确定的分支。

只利用会过早锁定看似优秀的动作,只探索则无法把预算集中到高价值区域。常用的上置信界形式为:

$$ \mathrm{UCB}_i = \bar{X}_i + C\sqrt{\frac{\ln N}{n_i}} $$

其中 $\bar{X}_i$ 是子节点 $i$ 的平均收益,$n_i$ 是该子节点访问次数,$N$ 是父节点访问次数,$C$ 控制探索强度。

第一项鼓励选择已知收益高的分支,第二项鼓励尝试访问较少的分支。随着 $n_i$ 增加,不确定性奖励逐渐减弱。

6. 计算预算与最终动作

MCTS 通常按以下预算之一终止:

  • 固定模拟次数。
  • 固定计算时间。
  • 固定内存或树节点数量。

终止后,可选择访问次数最多的根节点子分支,也可以选择平均收益最高的分支。访问次数通常更稳定;平均收益可能受少量幸运模拟影响。

实时游戏必须严格控制预算。MCTS 的优势是可以随时停止并给出当前最好答案,但动作模型、模拟速度和状态复制成本仍可能成为瓶颈。

7. MCTS 的优势与局限

优势:

  • 不需要完整展开巨大状态空间。
  • 搜索具有 anytime 特性,预算越多通常结果越好。
  • 各分支模拟相对独立,具备并行化潜力。
  • 行为具有一定多样性,不容易完全固定。

局限:

  • 状态与动作必须能够快速复制和模拟。
  • 实时连续世界难以直接建立精确模型。
  • 搜索质量依赖默认策略、奖励和预算。
  • 大量模拟仍可能无法覆盖关键但稀有的行动。

八、如何选择规划方法

场景特征 更适合的方法
行为流程较明确,需要设计者严格控制 HTN
目标明确,希望动作按环境动态组合 GOAP
状态空间巨大,可快速模拟未来结果 MCTS
强调即时反应、逻辑规模有限 行为树或状态机

选择时不能只看算法能力,还要评估状态表示成本、调试工具、设计师工作流、运行时预算和行为可预测性。越强大的自动规划,通常越需要更好的可视化和解释工具。

九、设计与工程原则

  1. 先定义 AI 能知道什么,再定义它能规划什么。
  2. 状态、前置条件与效果必须和实际 Gameplay 行为保持一致。
  3. 规划失败、执行失败和世界变化都应有明确的重规划策略。
  4. 用层级或启发式缩小搜索空间,不要把整个游戏世界直接交给规划器。
  5. 为计划、候选方法、动作代价和搜索统计提供可视化调试能力。

十、要点回顾

  1. 规划式 AI 通过世界状态、目标和动作动态生成行动序列。
  2. HTN 用领域知识把高层任务递归分解为可执行的基础任务。
  3. GOAP 把规划转为状态—动作图搜索,以动作代价比较不同计划。
  4. MCTS 通过选择、扩展、模拟与回传,在有限预算内探索巨大决策空间。
  5. UCB 同时考虑平均收益与访问不确定性,实现探索和利用之间的平衡。

参考资料