ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

游戏战斗系统学习第1篇:行为树(Behavior Tree, BT)

游戏战斗系统学习第1篇:行为树(Behavior Tree, BT) 一、行为树Behavior Tree, BT详解1. 什么是行为树行为树是一种层次化、可组合的行为控制架构常用于游戏 AI、机器人任务规划、自动化决策等场景。它把复杂行为拆成一棵树内部节点控制执行顺序、优先级、并行、装饰等叶子节点执行具体条件判断或动作每个节点被“tick”时返回三种状态之一Success成功Failure失败Running还在执行中需要下一帧/下一 tick 继续。行为树通常每个决策周期从根节点开始 tick根据节点返回状态决定下一步执行哪个分支。它不直接描述“当前处于哪个状态”而是描述“在当前环境下按什么优先级和组合方式选择行为”。2. 常见节点类型2.1 详解Sequence 顺序节点依次执行子节点,遇 Failure 返回 Failure遇 Running 返回 Running全 Success 返回 Success。结构图Sequence ├── Child 1 ├── Child 2 └── Child 3执行方向Child 1 ──Success── Child 2 ──Success── Child 3 │ │ │ Failure Failure Failure │ │ │ ▼ ▼ ▼ Failure Failure Failure语义解释Sequence 从左到右依次执行子节点子节点返回 Success继续执行下一个子节点子节点返回 Failure整个 Sequence 立即返回 Failure后续子节点不执行子节点返回 Running整个 Sequence 立即返回 Running后续子节点不执行所有子节点都返回 Success整个 Sequence 返回 Success总结Sequence 是“步骤链”必须按顺序全部成功才算成功。Sequence顺序节点伪代码tick Sequence: start 记忆模式 ? 上次 Running 的子节点索引 : 0 for i from start to 最后一个子节点: status tick(Child[i]) if status Running: 记录当前索引 i return Running if status Failure: 清除记忆 return Failure 清除记忆 return Success记忆模式无记忆 / 反应式 Sequence 每次 tick 都从 Child 1 重新开始。优点反应快前面条件变化能立刻发现。缺点如果前面动作有副作用可能被重复执行。有记忆 Sequence 记住上次执行到哪个子节点下一 tick 从该子节点继续不重新 tick 之前的子节点。优点避免重复执行已经成功的步骤。缺点前面条件变化时不一定能及时响应。示例Sequence ├── 检查有钥匙 ├── 开门 └── 进入房间如果“开门”返回 Running有记忆 Sequence 下一 tick 继续“开门”无记忆 Sequence 会重新检查“有钥匙”再执行“开门”。2.2 详解Selector / Fallback 选择 / 回退节点从左到右尝试遇 Success 返回 Success遇 Running 返回 Running全 Failure 返回 Failure直到一个成功结构图Selector / Fallback ├── Child 1 ← 最高优先级 ├── Child 2 └── Child 3 ← 兜底行为执行方向图Child 1 ──Failure── Child 2 ──Failure── Child 3 │ │ │ Success Success Success │ │ │ ▼ ▼ ▼ Success Success Success语义解释子节点返回 Failure继续尝试下一个子节点子节点返回 Success整个 Selector 立即返回 Success后续不执行子节点返回 Running整个 Selector 立即返回 Running后续不执行所有子节点都返回 Failure整个 Selector 返回 Failure总结Selector 是“优先级备选链”先试最高优先级不行再试下一个直到有一个成功或正在运行。Fallback 通常和 Selector 是同义词强调“前面的都失败时回退到后面的兜底行为”。选择 / 回退执行伪代码tick Selector: start 记忆模式 ? 上次 Running 的子节点索引 : 0 for i from start to 最后一个子节点: status tick(Child[i]) if status Success: 清除记忆 return Success if status Running: 记录当前索引 i return Running 清除记忆 return Failure记忆模式无记忆 / 反应式 Selector 每次 tick 都从 Child 1 重新评估。适合高优先级条件随时可能变化 或者需要快速打断当前行为有记忆 Selector 记住上次 Running 的子节点下一 tick 从该子节点继续。优点避免反复切换 缺点可能忽略更高优先级的新情况。关键点Selector 不表示“全部执行”而是“选一个执行”。左边的子节点优先级更高。无记忆 Selector 反应式强但可能频繁切换。有记忆 Selector 稳定但反应性弱。切换分支时旧分支的 Running 节点要清理。2.3 详解Parallel 并行节点同时 tick 多个子节点 按成功/失败阈值决定返回 Success / Failure / Running结构图Parallel [成功阈值1, 失败阈值3] ├── Child 1 ├── Child 2 └── Child 3执行方式图Parallel / | \ tick tick tick │ │ │ Child1 Child2 Child3 │ │ │ └─────┴─────┘ 统计成功/失败数量注意这里的“并行”通常不是多线程而是同一个 tick 内同时 tick 多个子节点逻辑上并行。语义解释Parallel 同时 tick 多个子节点然后根据策略判断整体结果。常见策略有两个阈值成功阈值 successThreshold需要多少个 Success 才算整体成功失败阈值 failureThreshold需要多少个 Failure 才算整体失败Parallel 并行节点执行伪代码tick Parallel: successCount 0 failureCount 0 for each child in children: if child 未完成: status tick(child) if status Success: successCount else if status Failure: failureCount if failureCount failureThreshold: halt 其他 Running 子节点 return Failure if successCount successThreshold: halt 其他 Running 子节点 return Success return Running关键点Parallel 不是真正的多线程只是逻辑并行。必须明确成功阈值和失败阈值否则语义不清晰。需要处理子节点之间的资源冲突例如两个动作同时控制移动。达到阈值后要停止未完成子节点。Running 子节点下一 tick 会被继续 tick。2.4 叶子节点 LeafCondition 条件 检查世界状态返回 Success/FailureAction 动作 执行具体行为可返回 Success/Failure/Running2.5 装饰器 Decorator装饰器是行为树中的一种单子节点它包装一个子节点用来修改子节点的执行方式、返回结果或执行时机。结构图Decorator └── Child它自己不直接执行具体动作而是“修饰”子节点。例如反转子节点的成功/失败重复执行子节点等等装饰器是行为树的“包装器”用来改变一个子节点的行为语义。装饰器执行模型装饰器的一般 tick 流程tick(Decorator) │ ├─ 前置逻辑条件、冷却、延迟、概率判断 │ ├─ 是否 tick 子节点 │ ├─ 否 → 直接返回 Success / Failure / Running │ └─ 是 → tick(Child) │ ├─ 后置逻辑转换结果、计数、计时、重试 │ └─ 返回最终状态常见装饰器分类详解1Inverter 反转器条件取反例如“没有看到敌人”把失败条件转成成功条件。Sequence ├── Inverter │ └── Condition 看到敌人 └── Action 巡逻表示没看到敌人时才巡逻。2Succeeder 成功包装器忽略子节点的失败让某个动作无论成功失败都继续后续流程。示例Sequence ├── Action 播放特效 ├── Succeeder │ └── Action 尝试拾取物品 └── Action 继续前进即使拾取失败也继续前进。3Failer 失败包装器强制失败 测试或阻断某个分支。4Repeat 重复执行重复执行子节点 N 次子节点返回 Success计数 1未达到 N 继续达到 N 返回 Success注意不同实现可能在一次 tick 内连续执行多次也可能每次 tick 只执行一次。行为树通常避免同 tick 无限循环。用途重复攻击 3 次重复巡逻路径重复播放动画。5Retry 重试子节点 Success整体返回 Success重置计数子节点 Failure重试次数 1未达 N 返回 Running达到 N 返回 Failure用途不稳定动作重试拾取物品失败后重试。6Timeout 超时子节点 Success / Failure直接返回并重置计时子节点 Running检查是否超时已超时halt 子节点返回 Failure。用途限时追击防止某个动作卡死。7Delay 延迟首次 tick 记录开始时间延迟未到返回 Running不 tick 子节点延迟到达tick 子节点并返回其结果用途等待动画播放延迟触发事件装饰器嵌套示例装饰器可以嵌套形成链Selector ├── Sequence 攻击 │ ├── Condition 看到敌人 │ ├── Retry(3) │ │ └── Action 瞄准 │ └── Cooldown(1s) │ └── Action 射击 │ ├── Sequence 逃跑 │ ├── Condition 血量低 │ └── Timeout(10s) │ └── Action 逃跑 │ └── Action 巡逻执行逻辑--- 根 Selector 先尝试攻击分支--- 看到敌人后执行“瞄准”--- 瞄准失败最多重试 3 次--- 瞄准成功后执行“射击”但受 1 秒冷却限制--- 如果血量低尝试逃跑分支--- 逃跑最多持续 10 秒超时则失败--- 都不满足则巡逻。这个例子展示了装饰器如何增强行为树的表达力。二、 行为树 BT 与有限状态机 FSM 的核心差异1. 差异对比总结FSM 是“状态迁移器”BT 是“行为组合器”。FSM (有限状态机): 系统显式地处于某个状态事件或条件触发状态转移。FSM 关注“我现在处于什么状态什么事件让我切换到下一个状态”BT (行为树): 系统没有全局显式状态而是每 tick 从根遍历一棵行为树按组合节点规则决定当前该做什么。BT 关注“我现在应该按什么优先级组合和执行哪些行为”。行为树是一种树形、可组合、tick 驱动、三态返回的行为控制架构适合表达复杂优先级和反应式行为。FSM 是一种显式状态、事件转移、图结构的控制模型适合状态清晰、转移简单的场景。2. 核心差异对比表控制模型--- 行为树 BT: 树形组合从根 tick隐式控制流--- 有限状态机 FSM: 显式状态 转移边当前状态是核心状态表示--- 行为树 BT: 无全局显式状态Running 节点、黑板、执行上下文表示进行中行为--- 有限状态机 FSM: 显式当前状态通常全局唯一转移机制--- 行为树 BT: 节点返回 Success/Failure/Running由组合节点决定下一步--- 有限状态机 FSM: 事件/条件触发显式转移反应性--- 行为树 BT: 每 tick 从根重新评估天然反应式--- 有限状态机 FSM: 通常事件驱动需显式定义转移适用场景--- 行为树 BT: 游戏 AI、机器人任务、复杂行为选择--- 有限状态机 FSM: 简单控制器、协议、UI、动画、模式切换3. 几个最关键差异详解案例状态显式 vs 状态隐式FSM 中当前状态是显式的巡逻 --看到敌人-- 追击 --进入攻击范围-- 攻击 --敌人丢失-- 巡逻BT 中没有“当前状态 追击”这种全局变量。它只有一棵树每 tick 从根开始Selector ├── 看到敌人 - 追击 - 攻击 ├── 血量低 - 逃跑 └── 巡逻“正在追击”可能表现为“追击节点返回 Running”但这不是 FSM 意义上的全局状态。显式转移 vs 隐式组合FSM 的控制流写在转移边上状态A --事件X-- 状态B 状态B --事件Y-- 状态CBT 的控制流写在树结构和节点返回规则里Selector 先试左分支失败再试右分支 Sequence 依次执行失败就中断。BT 的控制流是隐式的由组合节点语义决定。事件驱动 vs Tick 驱动FSM 通常由事件驱动--- 收到“看到敌人”事件 从巡逻转到追击--- 收到“血量低”事件 从追击转到逃跑。BT 通常由 tick 驱动--- 每帧/每周期从根 tick--- 条件重新评估--- 根据当前世界状态选择分支。因此 BT 更“反应式”FSM 更“事件式”。当然FSM 也可以每帧检查条件BT 也可以事件触发但典型风格不同。层次组合 vs 状态爆炸FSM 加功能时常常需要加状态和转移--- 巡逻、追击、攻击、逃跑、搜索、治疗、眩晕、死亡……--- 状态之间转移迅速增多容易形成“意大利面”。BT 加功能时通常是加一棵子树Selector ├── 战斗子树 ├── 生存子树 ├── 探索子树 └── 空闲子树子树可以独立开发、测试、复用。但 BT 也不是万能深层树和黑板耦合也会变复杂。并行能力BT 原生有 Parallel 节点可以同时执行多个行为例如一边移动一边播放动画一边检查条件 一边追踪目标一边保持距离。FSM 要实现并行通常需要并发状态机层次状态机 多个 FSM 并行运行 或者把并行逻辑塞进状态内部。三、 战斗游戏中使用案例案例1 Boss 多阶段战斗 AI1. 场景目标--- Boss 有 3 个阶段--- 阶段 1基础重击、追击--- 阶段 2火焰吐息、跳劈--- 阶段 3狂暴全屏 AOE、召唤小怪、冲锋--- 死亡优先级最高--- 被眩晕时能打断当前施法--- 技能有冷却冷却中自动降级到低优先级技能。2. 结构图Selector 根 ├── Sequence 死亡处理 │ ├── Condition SelfHP 0 │ └── Action 播放死亡/掉落 │ ├── Sequence 被控制中断施法 │ ├── Condition IsCasting │ ├── Condition IsStunned │ └── Action 中断施法 │ ├── Sequence 阶段3狂暴 │ ├── Condition Phase 3 │ └── Selector 阶段3技能 │ ├── Cooldown(10s) Sequence 全屏AOE │ │ ├── Condition TargetDistance 25 │ │ ├── Action 预警圈 │ │ └── Timeout(3s) Action 吟唱并释放AOE │ │ │ ├── Cooldown(8s) Sequence 召唤小怪 │ │ ├── Condition 场上小怪 3 │ │ └── Action 召唤小怪 │ │ │ ├── Cooldown(5s) Sequence 冲锋 │ │ ├── Condition TargetDistance 10 │ │ └── Action 冲锋到目标 │ │ │ └── Action 普攻 │ ├── Sequence 阶段2火焰 │ ├── Condition Phase 2 │ └── Selector 阶段2技能 │ ├── Cooldown(6s) Sequence 火焰吐息 │ │ ├── Condition 面向目标 │ │ ├── Condition TargetDistance 15 │ │ └── Timeout(2s) Action 吐息 │ │ │ ├── Cooldown(4s) Sequence 跳劈 │ │ ├── Condition TargetDistance 8 │ │ └── Action 跳劈 │ │ │ └── Action 普攻 │ ├── Sequence 阶段1基础 │ ├── Condition Phase 1 │ └── Selector 阶段1技能 │ ├── Cooldown(5s) Sequence 重击 │ │ ├── Condition TargetDistance 5 │ │ └── Action 重击 │ │ │ └── Action 追击或普攻 │ └── Action 待机3. 逻辑流程解析优先级设计根 Selector 从上到下1死亡2被控制打断施法3阶段 34阶段 25阶段 16待机。所以 Boss 每 tick 都会先判断“我是不是死了”“我是不是正在施法且被眩晕”。如果被眩晕会立刻中断当前施法而不是继续吟唱。阶段内技能选择每个阶段内部又是一个 Selector。例如阶段 2Selector 阶段2技能├── 火焰吐息├── 跳劈└── 普攻解析--- 火焰吐息冷却好了且面向目标、距离小于 15执行吐息--- 吐息返回 Running阶段 2 Selector 返回 Running根也返回 Running--- 下一 tick 从根重新开始仍然先检查死亡、打断、阶段--- 如果吐息冷却中Cooldown(6s) 返回 Failure阶段 2 Selector 继续尝试“跳劈”--- 跳劈也失败则执行普攻。装饰器作用--- Cooldown让技能冷却时返回 Failure从而让 Selector 自动降级到下一个技能--- Timeout防止吟唱类技能卡死例如 AOE 吟唱最多 3 秒超时则中断并失败案例2 远程法师/弓箭手风筝 AI1. 场景目标远程单位需要--- 血量极低时闪现、喝药、逃跑--- 施法时被近身立刻中断施法并后跳--- 被近身时优先冰环击退否则后撤--- 敌人多时放 AOE--- 敌人靠近时放减速--- 距离合适时火球输出--- 太近则保持距离。2. 结构图Selector 根 ├── Sequence 濒死保命 │ ├── Condition SelfHP 30% │ └── Selector 保命手段 │ ├── Cooldown(20s) Action 闪现 │ ├── Cooldown(30s) Action 喝药 │ └── Action 逃跑 │ ├── Sequence 中断施法并脱离 │ ├── Condition IsCasting │ ├── Condition TargetDistance 5 │ └── Action 中断施法并后跳 │ ├── Sequence 被近身处理 │ ├── Condition TargetDistance 5 │ └── Selector 近身应对 │ ├── Cooldown(8s) Action 冰环或击退 │ └── Action 后撤 │ ├── Selector 输出循环 │ ├── Cooldown(12s) Sequence AOE │ │ ├── Condition EnemyCount 3 │ │ ├── Condition TargetDistance 在 8~20 │ │ └── Timeout(3s) Action 暴风雪 │ │ │ ├── Cooldown(6s) Sequence 控制 │ │ ├── Condition 敌人正在靠近 │ │ └── Action 减速 │ │ │ ├── Cooldown(1.5s) Sequence 单体输出 │ │ ├── Condition TargetDistance 在 8~20 │ │ └── Action 火球 │ │ │ └── Sequence 保持距离 │ ├── Condition TargetDistance 8 │ └── Action 后撤 │ └── Action 调整站位或待机3. 逻辑流程解析优先级设计根 Selector 优先级1濒死保命2施法中被近身立即中断3被近身处理4输出循环5调整站位。这体现了远程 AI 的核心原则生存 脱离控制 保持距离 输出。案例3近战小怪小队协同 AI1. 场景目标一群哥布林战士围攻玩家--- 血量低且队友少时后撤并呼叫支援--- 玩家正在施法时尝试投网或冲锋打断--- 如果目标不是自己尝试包抄到侧后方--- 玩家攻击预警时概率闪避或格挡--- 距离远则追击距离近则普攻2. 结构图Selector 根 ├── Sequence 撤退呼叫支援 │ ├── Condition SelfHP 20% │ ├── Condition AllyCount 2 │ └── Parallel [成功2, 失败1] │ ├── Action 后撤到安全点 │ └── Action 呼叫支援 │ ├── Sequence 打断玩家施法 │ ├── Condition TargetIsCasting │ ├── Cooldown(10s) Sequence 投网/冲锋打断 │ │ ├── Condition TargetDistance 12 │ │ └── Action 投网或冲锋打断 │ └── Action 攻击 │ ├── Selector 战斗行为 │ ├── Sequence 包抄攻击 │ │ ├── Condition 目标不是自己 │ │ ├── Condition 有可用包抄点 │ │ ├── Action 移动到侧后方 │ │ └── Action 攻击 │ │ │ ├── Sequence 闪避 │ │ ├── Condition IncomingAttack │ │ ├── Cooldown(2s) │ │ └── Action 闪避或格挡 │ │ │ ├── Sequence 追击攻击 │ │ ├── Condition TargetDistance 攻击范围 │ │ └── Action 追击 │ │ │ └── Action 普攻 │ └── Action 巡逻或待机3. 逻辑流程解析优先级设计根 Selector 优先级1撤退呼叫支援生存优先2打断玩家施法战术控制3包抄攻击协同输出4闪避防御5追击攻击常规输出6巡逻待机。
返回列表