obsidian/笔记文件/2.笔记/GOAP 目标导向型行为计划 AI 算法.md
2025-03-26 00:02:56 +08:00

6.9 KiB
Raw Permalink Blame History

#unity/日常积累

GOAP 目标导向型行为计划 AI 算法 全称: Goal-Oriented Action Planning

游戏开发AI 实现,一般就是 FSM(有限状态机)、HFSM(分层/层次有限状态机)、BehaviorTree(行为树) 他们需要提前设计好 行为、状态之间的切换 当需要添加或者减少 行为、状态 的时候,需要重新配置,甚至需要挺大的改动 FSM(有限状态机)、HFSM(分层/层次有限状态机)、BehaviorTree(行为树) 这种根据配置,读取环境信息,然后根据配置找到分支,然后找到执行的行为,属于 Reactive AI(反应型 AI先接受刺激输入然后执行对应行为)

目标导向型行动计划简称GOAP 是让AI 自己去找到解决问题的方法 是一种能够轻松呈现给你的代理选择的AI系统也是帮助你可以无需维持一个庞大且复杂的有限状态机、行为树 而做出明智决策的机器GOAP 属于 慎思型AI 将环境和背景条件纳入决策考量,可以胜任复杂决策

目标导向型行为计划,参考 STRIPS-like专门设计用于游戏中自主角色行为实时控制的规划体系结构。 STRIPS规划的简单介绍 STRIPS是由斯坦福大学StanfordUniversity于1970年开发的名称是斯坦福研究所问题解决者Stanford Research Problem Solver的首字母缩写。 一个Action只有在其所有前提条件都得到满足的情况下才能执行并且每个动作都会以某种方式改变世界的状态

四个主要类: 1.Agent代理 主体,负责连接各个类,主要逻辑在这里运行,游戏中可以是 Player、NPC 等具体的实现类AI 就是控制 Agent 执行各种行为的。

2.Action:动作: 可以被执行的动作,比如:拿东西、丢东西、吃饭、伐木等, 每个 Action 有需要有:执行的先决条件 preCondition执行后的效果 effect 每个 Action 的执行需要设定一个代价Cost 如 吃饭行为 执行的先决条件:饿了、 有食物 执行后的效果: 解决饥饿 如 伐木行为 执行的先决条件:有树木、有斧头 执行后的效果:获得木头

3.IGoap: 数据提供者,提供给 Agent 目标和反馈是否成功失败等等主要用于描述世界状态简称环境变量、Agent 目标 环境变量:有树木、有斧头、有食物、体力值、拥有金币数、有矿山、矿山位置 Agent 目标:拥有木头、解决饥饿、获得金币、获取矿石

4.Planer 决策者, 通过各个类来决策出最优的路线供Agent使用 执行逻辑:大体思路是依据 AStar 寻路算法的思想,从目标开始往前查找 Action如果Action 的效果能够完成至少一个目标,则将 Action 的效果写入到环境变量,然后将 Action 的前置条件写入到目标,继续往前查找

下面名词解释action 行为worldStatus 环境变量agentGoal 目标, cost 消耗值Action preCondition 先决条件Action effect 执行效果

逻辑图如下

!Pasted image 20240409142834.png

下面伪代码展示下 Planer 执行逻辑

    worldStatus -- 环境变量
    agentGoal   -- Agent 目标
    
    获取所有可用的 Action,并依据Action的 Cost 从小到大排序得到 ActionList

    local resultNode = nil   -- 最终结果
    local heap = Heap.new()  -- 创建小根堆
    
    local parentNode = nil
    local action = nil
    local cost = 0
    local node = Node.new(parentNode action, worldStatus, agentGoal, cost)
    
    heap.insert(node)
    while heap.count > 0 do
        local node = heap.DelNode()  -- 获取堆顶节点并且删除
        -- node.action 不为空 并且 node 的先决条件 preCondition 都包含在 node.worldStatus
        if (null ~= node.action) and action.preCondition.IsContainIn(node.worldStatus) then
            -- 最终可执行的结果
            resultNode = node
            break
        end
        
        foreach action in ActionList do  -- 遍历所有 Action
            -- 如果 action 不可用,跳过
            if not action.EnableUse() then
                continue
            end
            local newWorldStatus = node.worldStatus.Clone()  -- 节点的 环境变量 克隆一份
            local newAgentGoal = node.agentGoal.Clone()      -- 节点的 Agent目标 克隆一份
            -- 要求 Action 的执行效果 action.effect至少有一个包含在agentGoal
            if not action.effect.IsAnyContain(node.agentGoal) then  
                continue
            end
 
            -- 要求 action 的先决条件与不能与目标冲突
            if (action.preCondition.HasAnyConflict(goalStatus)) then
                continue
            end
            -- 筛选出来一个可以执行的 Action 了
            -- 将 action 的执行效果(action.effect),写入到 新的环境变量(newWorldStatus)中
            newWorldStatus.AddFrom(action.effect)
            -- 将 action 的执行效果(action.effect),从 新Agent目标(newAgentGoal)中移除
            newAgentGoal.RemoveFromStatus(action.effect) 
            -- 将 action 的先决条件(action.preCondition) 中的值写入 newAgentGoal
            newAgentGoal.AddFromStatus(action.preCondition);
            
            local cost = node.cost + action.cost
            local newNode = Node.new(node, action, newWorldStatus, newAgentGoal, cost)
            heap.Insert(newNode)
        do
    end

    if nil == resultNode then
        return
    end
    local stack = stack .new()  -- 栈LIFO 后进先出
    while nil ~= resultNode and resultNode .parentNode ~= nil do
        local parentNode = resultNode .parentNode
        queue.Push(parentNode)
        resultNode = resultNode .parentNode
    end

例子:
AI 饿了,要找 食物 填饱肚子,
环境状态包含: 饿了
AI 的目标就是 解决饥饿

每个行为都是有先决条件和执行效果。行为是否能够执行必须要行为的效果是否能达成目标,然后是先决条件是否满足

!Pasted image 20240409142927.png

以上五中行为可以组合成 3 组 达到 解决饥饿 的目的。

!Pasted image 20240409142933.png

GOAP 缺点 1.GOAP学习成本偏高 2.GOAP默认不保证Action顺序如果我们想要强制指定顺序需要额外加State就像上面那个例子一样但是一般而言我们的AI也不会去在意这种无关紧要的顺序因为重要的顺序我们已经规范好了。 3.GOAP毕竟使用了运行时规划会对游戏性能产生一定的影响但是这种目标导向的A*规划在AI复杂的情况下性能并不一定比FSM/行为树弱

GOAP优点 1.解耦目标和行为设计时可以更加专注的设计AI的行为不用过多考虑目标新增减少Action非常方便不会像FSM/行为树那样具有那么强的入侵性和破坏性,提高了开发效率 2.动态规划的能力这会使我们的AI看起来更加“智能” 3.配置方便易于理解完全可以让策划使用EXCEL接管AI开发工作