← ALL ARTICLES
游戏AI5 MIN READ

效用评分与目标规划

全库目录221
本文目录9

守卫受伤时,决策先比较继续交战、搜寻和撤退的可行性,再把选中的目标展开成具体动作。本页输入为只读事实快照、候选门禁与偏好、有限动作模型,输出为目标和有序原子步骤。执行与取消由状态机与行为树负责,候选的正式采用见决策计划提交。

效用评分与动作切换

行为树可以执行交战中的接近和攻击,受伤以后是否值得继续交战,则需要比较交战、搜寻与撤退。效用系统先排除做不到的目标模式,再比较可行候选,选择结果经HFSM和计划进入同一取消与接纳接口。

必要条件与偏好

效用系统(Utility AI)比较此刻各行为的价值。先用布尔门禁判断目标、弹药、路径和冷却等必要条件,再给可行行为计算偏好分数。本页的偏好采用加权几何平均:

U=exp⁡(∑iwilog⁡max⁡(si,ϵ)∑iwi).U=\exp\left(\frac{\sum_i w_i\log\max(s_i,\epsilon)}{\sum_i w_i}\right).

每个原始输入先按已配置区间归一化,曲线输出s在[0,1],权重w为正,ε取10⁻⁶。越界有限值可按规则夹到区间;非有限值或无效配置产生诊断,并把该候选判为不可用;累加溢出也按配置错误拒绝。必要条件为假直接拒绝,不能让ε把“没有弹药”变成微小却合法的射击概率。

text
ScoreAction(action, snapshot):
    if any necessary condition is false: return Ineligible
    if preferences is empty: return Eligible(1)
    logSum = 0; weightSum = 0
    for preference in preferences:
        require finite input, valid normalization range, finite weight > 0
        curveValue = curve(normalize(input))
        require finite curveValue
        s = clamp(curveValue, 0, 1)
        logSum += weight * log(max(s, 0.000001))
        weightSum += weight
        if not finite(logSum) or not finite(weightSum): return Ineligible
    require weightSum > 0
    return Eligible(exp(logSum / weightSum))

三个同权0.8偏好和一个0.8偏好都会得到0.8;直接连乘则是0.512与0.8,差异只来自条目数量。几何平均保留低分压低总体偏好的性质,但偏好零分经数值下限仍是很小的正数。确实需要否决行为的条件放在门禁里,不与偏好混用。空偏好列表在本页取常量1,适合只受门禁控制的明确动作;设计者须将这个常量与其他动作的评分一起审查。

迟滞与失效优先级

普通切换要求新动作分数与当前分数之差严格大于0.1,且当前动作已持续0.3秒。两项门槛只在当前动作仍可行且正在运行时适用。每次重评估先检查当前门禁和执行终态:目标销毁、路径失败、弹药耗尽或动作已结束,都直接进入停止或重新选择流程,绕过分差与持续时间。紧急事件按预定事件优先级选择可行的应急动作,同样绕过两项门槛;紧急不能绕过动作自己的必要条件。

当前交战0.75,新搜寻0.82,普通变化保留交战;新撤退0.9且当前模式持续0.4秒才触发普通切换。若敌人已销毁,即使交战只运行0.05秒、搜寻只有0.2,也先退出失效交战并取消其中的活动动作,再进入搜寻。没有可行候选就进入无外部预约的待机,不保持已经失效的动作。

选择最高分时用稳定行为ID打破平分。停止旧动作后,候选还要经过资源释放与最新门禁检查;等待取消期间若候选也失效,重新选择即可,旧动作不会重新获得执行权。随机选择是另一种项目策略,需要保存分布、种子和随机消费顺序,本页具体路线采用确定性最高分。

目标规划与执行

撤退候选得分最高,并不意味着守卫已经知道怎样进入掩体。若它还需补弹、拿钥匙或开门,规划器把目标展开成有前后依赖的动作,执行器逐步核对真实结果。

GOAP回归搜索

目标导向行动规划(GOAP)用有限事实描述状态,动作用前提、效果和有限非负成本描述转换。受伤守卫当前既无弹药也未在掩体,目标是“有弹药且在掩体”。补弹动作使弹药为真但离开掩体,进入掩体动作保持弹药并使在掩体为真,搜索可以找到先补弹再进入掩体的次序。连续距离等输入按任务需要离散成有限区间,成本的时间、风险与消耗先统一尺度,避免状态数量和成本单位失控。

规划的反向搜索

cpp
Plan GoapPlan(WorldState start, Goal goal, Action[] actions)
{
    bestCost[goal.facts] = 0; // 其他事实集的默认成本为无穷;动作成本非负
    open.Push({ goal.facts, {}, 0 });           // 待满足事实、已选动作、累计成本
    while (!open.IsEmpty()) {
        Node node = open.PopLowestCost();
        if (node.cost != bestCost[node.required]) continue;
        if (start.Satisfies(node.required))     // 当前世界已满足全部剩余前提
            return Reverse(node.actions);
        foreach (Action& action in actions) {
            if (!action.effects.SatisfiesAny(node.required)) continue;
            if (action.effects.ConflictsWith(node.required)) continue;
            Facts remaining = RemoveAssignedKeys(node.required, action.effects);
            remaining.MergeRequirements(action.preconds);
            if (remaining.ContainsContradictoryValues()) continue;
            if (node.cost + action.cost >= bestCost[remaining]) continue;
            bestCost[remaining] = node.cost + action.cost;
            open.Push({ remaining, node.actions + action,
                        node.cost + action.cost });
        }
    }
    return null;
}

这是采用C++外观的回归规划伪代码,类型与集合接口用于说明机制,不能直接编译。每步用动作效果满足部分目标,再把动作前提加入剩余需求。片段将目标、前提与赋值效果表示成有限键值映射。SatisfiesAny要求至少一项效果与剩余需求同键同值;ConflictsWith检查同键异值,布尔假值也作为显式效果处理。RemoveAssignedKeys删除本动作已经满足的需求,MergeRequirements合并前提并保留冲突标记,随后检查同一键的矛盾值。bestCost按规范化事实集合索引,默认无穷;完整实现还需搜索预算、稳定平局规则和具体状态编码,冲突例子见下文。当前状态尚未满足某项前提时,其他动作可能建立它,不能据此直接剪枝。布尔事实可用位掩码保存;多值状态需要显式的键值表示与冲突规则。

计划只是意图,不保证底层动作一定成功。执行器要报告完成、失败、取消和超时,规划器据此更新事实。调试时同时保存搜索过的状态、被拒绝的前提和最终成本。

回归时若把“冲出掩体捡弹药”直接作为最后动作,它把“在掩体”赋为假,与剩余需求中的真值冲突,应拒绝这个位置。先选择“进入掩体”作为最后动作,再回归到补弹,则可以形成合法的“补弹→进入掩体”。这说明负效果检查针对本次剩余目标,不能把会破坏某项事实的动作永久禁用。

搜索队列按成本、稳定动作ID排序,事实集合采用固定键序列作为去重键;到达预设的展开节点上限(例如每次5000个)返回预算耗尽,不把未完成搜索当成证明无计划。零成本循环只在改善某个事实集的最佳成本时重新入队。执行时逐步复查前提,失败报告实际世界事实并重规划。

HTN分解与状态推进

层次任务网络(HTN)用领域方法将复合任务拆成子任务。同一守卫需要撤退时,领域方法可按门状态选择[进入掩体],或[取得钥匙,开门,进入掩体]。规划器的节点保存临时状态、待展开任务列表与原子计划;取首任务,原子动作满足前提时应用效果并追加计划,复合任务则按方法顺序把子任务插到列表头。

假设掩体在锁门之后,第一个方法要求门已开启,前提不满足,规划器恢复该方法展开前的临时状态,再尝试[取得钥匙,开门,进入掩体]。取得钥匙的效果先写入临时状态,开门才会通过;方法失败时连同这份临时效果一起丢弃。相同临时状态与待展开任务组合去重,并限制分解深度,防止递归方法无限展开。

临时推演只用于找计划。真实执行取得钥匙失败,世界里仍没有钥匙,执行器不会继续开门,也不会把规划快照写回场景。GOAP与HTN都把原子动作交给决策输入与动作交接所述的宿主动作账本,只有宿主确认成功才推进计划;取消时按活动实例释放资源,未开始的计划后缀直接丢弃。

实现与证据

行为树、效用和GOAP正文为机制片段;上述评分函数采用项目示例策略,GOAP搜索为伪代码。有限键值GOAP模型通过3项回归检查:拒绝破坏目标的末动作、先破坏后重建事实、零成本循环终止;运行 python 知识库/examples/revision_16_21/test_review_reference.py 可复现。完整NPC框架、异步动作与行为树中止尚未接入运行。

相关主题

参考资料

效用聚合、切换门槛及HTN展开按本页给定模型定义,GOAP代码为有限键值回归搜索伪代码。