概述
GOAP 即目标导向行动规划(Goal Oriented Action Planning),是一种用于AI决策的技术,广泛应用于游戏开发等领域,让智能体能够根据目标和当前状态制定行动计划。
在本项目中,GOAP 是一个使用贪婪深度优先搜索(DFS)算法的简单 GOAP 系统,适用于 Unity 项目,让智能体能够根据目标和当前状态制定行动计划。
核心概念
目标(Goal)
- 定义:代表智能体想要达成的状态或结果,由
AgentGoal
类表示。
goals.Add(new AgentGoal.Builder("Chill Out")
.WithPriority(1)
.WithDesiredEffect(beliefs["Nothing"])
.Build());
- 说明:创建了一个名为 “Chill Out” 的目标,优先级为 1,期望达成 “Nothing” 这个信念所代表的状态。
行动(Action)
- 定义:智能体为了实现目标可以执行的具体操作,由
AgentAction
类表示。
actions.Add(new AgentAction.Builder("Relax")
.WithStrategy(new IdleStrategy(5))
.AddEffect(beliefs["Nothing"])
.Build());
- 说明:创建了一个名为 “Relax” 的行动,采用
IdleStrategy
策略,执行该行动会产生 “Nothing” 这个信念所代表的效果。
信念(Belief)
- 定义:用于描述智能体对环境的认知和判断条件,由
AgentBelief
类表示。
factory.AddBelief("AgentIdle", () => !navMeshAgent.hasPath);
- 说明:创建了一个名为 “AgentIdle” 的信念,其判断条件是导航网格代理没有路径。
规划器(Planner)
- 定义:负责根据目标和可用行动生成行动计划,由
GoapPlanner
类实现。
var potentialPlan = gPlanner.Plan(this, goalsToCheck, lastGoal);
- 说明:调用
GoapPlanner
的Plan
方法,为智能体生成行动计划。
工作流程
1. 初始化
在 GoapAgent
类的 Start
方法中,调用 SetupBeliefs
、SetupActions
和 SetupGoals
方法分别初始化智能体的信念、可用行动和目标。
void Start() {
SetupTimers();
SetupBeliefs();
SetupActions();
SetupGoals();
}
2. 规划生成
当智能体需要执行新的行动或目标发生变化时,调用 CalculatePlan
方法,该方法会调用 GoapPlanner
的 Plan
方法生成行动计划。
void CalculatePlan() {
var priorityLevel = currentGoal?.Priority ?? 0;
HashSet<AgentGoal> goalsToCheck = goals;
if (currentGoal != null) {
goalsToCheck = new HashSet<AgentGoal>(goals.Where(g => g.Priority > priorityLevel));
}
var potentialPlan = gPlanner.Plan(this, goalsToCheck, lastGoal);
if (potentialPlan != null) {
actionPlan = potentialPlan;
}
}
3. 行动执行
智能体按照生成的行动计划依次执行行动,每个行动有对应的执行策略(如 AttackStrategy
、MoveStrategy
等),在 Update
方法中更新行动状态,直到行动完成。
void Update() {
statsTimer.Tick(Time.deltaTime);
animations.SetSpeed(navMeshAgent.velocity.magnitude);
if (currentAction == null) {
CalculatePlan();
if (actionPlan != null && actionPlan.Actions.Count > 0) {
navMeshAgent.ResetPath();
currentGoal = actionPlan.AgentGoal;
currentAction = actionPlan.Actions.Pop();
if (currentAction.Preconditions.All(b => b.Evaluate())) {
currentAction.Start();
} else {
currentAction = null;
currentGoal = null;
}
}
}
if (actionPlan != null && currentAction != null) {
currentAction.Update(Time.deltaTime);
if (currentAction.Complete) {
currentAction.Stop();
currentAction = null;
if (actionPlan.Actions.Count == 0) {
lastGoal = currentGoal;
currentGoal = null;
}
}
}
}
4. 动态调整
如果环境发生变化(如目标位置改变),智能体会重新评估目标和计划,生成新的行动计划。
关键类和方法
GoapAgent
- 作用:代表智能体,负责初始化、规划生成和行动执行。
- 关键方法:
SetupBeliefs
:初始化智能体的信念。SetupActions
:初始化智能体的可用行动。SetupGoals
:初始化智能体的目标。CalculatePlan
:生成行动计划。Update
:更新智能体的状态和执行行动。
GoapPlanner
- 作用:根据目标和可用行动生成行动计划。
- 关键方法:
Plan
:主规划方法,使用贪婪 DFS 算法寻找实现目标的行动序列。FindPath
:递归查找路径,尝试满足目标的所有效果。
AgentAction
- 作用:表示智能体的行动,包含前置条件、效果和执行策略。
- 关键方法:
Start
:开始执行行动。Update
:更新行动状态。Stop
:停止执行行动。
AgentBelief
- 作用:表示智能体的信念,包含判断条件和观察位置。
- 关键方法:
Evaluate
:评估信念是否成立。
AgentGoal
- 作用:表示智能体的目标,包含优先级和期望效果。
优缺点及优化方向
优点
- 灵活:智能体可以根据不同的目标和环境状态动态调整行动计划。
- 适应性强:能够处理复杂的目标和行动组合。
局限性
- 计算复杂:在有多个目标和大量可用行动的情况下,规划出最佳行动序列的计算量会很大。
- 难维护:涉及多个组件(如目标、行动、规划器等),修改一个组件可能会影响其他组件,维护难度高。
优化方向
- 使用更高效的搜索算法:如 A* 算法[[AStar寻路]],提高规划效率。
- 模块化设计:将不同的功能模块分离,提高代码的可维护性。
- 可视化编辑:创建可视化的编辑器,方便用户配置目标、行动和信念
与行为树、FSM对比
核心原理对比
- FSM: 将 AI 行为划分为多个独立状态,每个状态定义特定行为,通过条件判断实现状态转移。
- 行为树: 通过树状结构组织行为节点,从根节点到叶节点按规则遍历,决定执行的动作。
- GOAP: 基于 “目标 - 动作” 的逻辑,通过规划算法生成实现目标的最优动作序列。
优缺点对比分析
1. FSM:简单高效但缺乏灵活性
- 优点:
- 实现简单,逻辑直观,适合快速开发;
- 性能消耗极低,适合大量 AI 同时运行。
- 缺点:
- 状态间耦合强,复杂逻辑会导致 “状态爆炸”(如 10 个状态可能有 90 条转移路径);
- 难以复用代码,修改成本高。
2. 行为树:结构化设计的 “平衡解”
- 优点:
- 分层设计清晰,可复用节点;
- 支持并行行为;
- 缺点:
- 复杂树结构调试困难(如多层嵌套节点的优先级冲突);
- 无法动态调整目标(需手动修改树结构才能改变行为目标)。
3. GOAP:智能但成本高的 “动态规划”
- 优点:
- 真正实现 “目标导向”,AI 可自主选择达成目标的最优路径;
- 环境适应性强,可应对未预设的情况。
- 缺点:
- 状态建模复杂,需精确定义每个动作的前提条件和效果;
- 规划算法消耗大,大量 AI 同时规划可能会导致卡顿;
- 难以调试,动态生成的序列可能不符合预期。
如何选择合适的AI架构?
可以根据对于AI逻辑的复杂程度进行选择
-
FSM:适用于AI逻辑简单,状态少,无需动态调整的场景
-
行为树:适用于处理复杂分层的AI逻辑,且需要可视化编辑时
-
GOAP:当AI需要“智能决策”(如可以自主调整目标),且场景交互复杂度高(如开放世界NPC的行为)时
其实三者完全是可以结合使用的,在复杂场景中为实现不同需求各取所长,例如:用行为树作为顶层逻辑框架,作为NPC主逻辑流程;在有一个明确的目标需求时使用Goap处理决策规划;在特定节点中嵌入FSM细分一些动作。以平衡灵活性和性能