修改文档

This commit is contained in:
gongxh
2025-09-29 10:14:04 +08:00
parent 260a8badae
commit 05b5c7fad5

View File

@@ -1,18 +1,19 @@
# 硬核游戏开发 - 使用BehaviorTree实现游戏AI决策的开发详解 # 硬核游戏开发 - 使用BehaviorTree实现游戏AI决策的开发详解
## 🎮 一个让策划抓狂的Bug ## 一个让我头疼三个月的BOSS
> "这个BOSS太蠢了它明明看到玩家了为什么还在那里发呆" 去年在公司做一个RPG项目的时候遇到了一个特别头疼的问题。策划给我扔了个需求做一个龙王BOSS要求这货能巡逻、能战斗、血少了会发疯、快死了还会逃跑。
这是我在某公司实习时听到最多的一句话。那是一个魔幻RPG项目我负责实现一个"智能"的龙王BOSS。按照策划的设计文档这个BOSS应该能够 听起来挺简单的不就是几个状态切换嘛。我当时想都没想直接上手就是一顿if-else
- 🔍 **侦察阶段**:在玩家进入领域前巡逻,警戒四周 按策划的文档这个BOSS需要
- ⚔️ **战斗阶段**:发现玩家后立即进入战斗状态,根据距离选择近战或远程攻击 - 平时在那巡逻,看到玩家就冲过去
- 🩸 **血怒阶段**血量低于30%时进入狂暴模式,攻击力翻倍 - 根据距离选择近战还是远程攻击
- 🛡️ **防御阶段**:受到大量伤害时短暂防御,恢复少量血量 - 血量掉到30%以下就进入狂暴模式
- 💨 **逃跑阶段**:血量极低时尝试逃跑,寻找掩体 - 受到重击时会短暂防御
- 血量太低就开始逃跑
起来很简单对吧?我天真地用了一堆 `if-else` 语句 起来逻辑很清楚,我就写了一大堆判断
```javascript ```javascript
function updateBoss() { function updateBoss() {
@@ -42,22 +43,19 @@ function updateBoss() {
} }
``` ```
**结果?** 一场灾难 结果呢?完全是个灾难
- BOSS经常在攻击和防御之间疯狂切换 BOSS的表现简直让人抓狂有时候明明看到玩家了突然又开始巡逻血都快没了还在那疯狂攻击更离谱的是防御和攻击状态之间来回切换看起来像个神经病。
- 有时候明明发现了玩家,却突然开始巡逻
- 血怒状态下居然还会尝试逃跑
- 最要命的是:每次策划要求调整优先级,我都要重写整个逻辑!
三个通宵后,我的代码成了一个800行的意大利面条连我自己都看不懂了。更糟糕的是每次修复一个bug就会产生三个新bug 策划每天都来找我:"这BOSS怎么这么蠢"我也很绝望啊,每次改一个地方,其他地方就出新问题。最后代码成了800行的意大利面条,连我自己都不敢动了
**直到我遇到了行为树...** 后来一个老同事看不下去了,跟我说:"你试试行为树吧,专门解决这种问题的。"
一周后同样的BOSS逻辑我用行为树重新实现了 花了差不多一周时间学习和重构用行为树重新写了这个BOSS
``` ```
龙王BOSS行为树 龙王BOSS行为树
根节点(优先选择器) 根节点(选择器)
├── 逃跑分支(血量 < 10% ├── 逃跑分支(血量 < 10%
│ ├── 寻找掩体 │ ├── 寻找掩体
│ └── 快速移动 │ └── 快速移动
@@ -76,177 +74,141 @@ function updateBoss() {
└── 警戒四周 └── 警戒四周
``` ```
**奇迹发生了!** 效果立竿见影!
- ✅ BOSS行为逻辑清晰优先级明确 BOSS终于不再像个智障了行为逻辑变得很清晰。最关键的是策划现在能直接看懂这个结构提需求的时候也更明确了。代码从800行缩减到200多行维护起来轻松了不少。
- ✅ 策划可以直接看懂并提出修改意见
- ✅ 新增行为只需要添加新分支,不影响现有逻辑
- ✅ 调试时可以清楚看到每一步的决策过程
- ✅ 代码从800行缩减到200行可读性提升10倍
更重要的是,当策划说"能不能让BOSS在血量50%时召唤小怪",我只需要在行为树中插入一个新分支,5分钟搞定 最让我印象深刻的是,后来策划突然说要加个"血量50%时召唤小怪"的功能,我只在行为树里插了个新分支,十几分钟搞定了。要是放在以前的if-else结构里估计又得折腾好几天。
--- ---
**这就是行为树的魅力。** 这就是我第一次接触行为树的经历。
作为一名游戏开发者你是否也遇到过类似的问题当游戏中的怪物、NPC需要表现出复杂行为时——巡逻、追击、逃跑、施法、观察环境并做出判断——背后往往不应该是一条又一条 if-else 的堆叠,而是一套清晰、可扩展、可调试的决策框架:**行为树Behavior Tree** 如果你也在做游戏开发特别是涉及到AI逻辑的部分可能也遇到过类似的问题。怪物AI、NPC行为、甚至一些复杂的游戏机制用传统的if-else或者状态机来实现总是容易变成一团乱麻
本指南将带你从零开始认识行为树,让你也能构建出让策划赞不绝口的游戏 AI 决策系统! 行为树提供了一个更好的解决方案。下面我就把这段时间学到的东西整理一下,希望能帮到有同样困扰的朋友。
## 一、开篇 ## 什么是行为树
行为树是一种用于描述 AI 决策逻辑的树形结构由根节点驱动组合节点如「选择器」「序列」负责控制流程装饰节点用于修饰行为叶子节点则执行具体动作或进行条件判断。相较有限状态机FSM行为树更易组合与复用能自然表达“尝试 A 否则 B”“按顺序执行直到成功”等复杂模式并且非常适合可视化编辑与热更新 简单来说,行为树是一种树形结构,用来描述AI决策逻辑。
## 二、行为树执行流程 - 一个哥布林的日常决策 它的基本思路是这样的:从根节点开始,通过不同类型的节点来控制执行流程。比如"选择器"节点会依次尝试它的子节点,直到有一个成功为止;"序列"节点则要求所有子节点都成功才算成功。最底层的叶子节点负责执行具体的动作或者判断条件。
想象一下,你是一只聪明的哥布林守卫,正在洞穴门口值班。每一秒钟,你的大脑都在运转着一套复杂的决策系统——这就是行为树! 相比传统的状态机,行为树最大的优势是更容易组合和复用。你可以很自然地表达"先试试A不行就试B"或者"按顺序执行1、2、3"这样的逻辑,而且特别适合做可视化编辑器。
### 1. 三种人生状态(节点状态) ## 行为树是怎么工作的
就像人生一样,行为树中的每个节点都只有三种可能的状态: 为了更好理解我们来看一个简单的例子。假设你在做一个哥布林守卫的AI它需要在洞穴门口巡逻。
* **成功** ✅ - "太好了!任务完成!" ### 节点的三种状态
* **失败** ❌ - "唉,这条路走不通..."
* **运行中** ⏳ - "别催,我还在努力呢!"
这就像你在思考"今晚吃什么"时的状态:要么想到了(成功),要么放弃了(失败),要么还在纠结中(运行中)。 行为树中的每个节点在执行时只会返回三种状态之一:
### 2. 决策节点大家族 - 每个都有自己的性格 * **成功** - 任务完成了
* **失败** - 这条路走不通
* **运行中** - 还在执行中,需要等待
#### 2.1 选择节点 - "备胎专家" 这个概念其实很好理解,就像你在做任何事情时的状态一样:要么做完了,要么做不了,要么还在做。
**性格特点**永不放弃的乐观主义者总是有Plan B、Plan C... ### 几种常用的节点类型
想象你是个饿肚子的哥布林,面前有三个选择: #### 选择器节点Selector
1. 去厨房找剩菜
2. 去花园抓虫子
3. 啃树皮充饥
选择节点就像一个不死心的你: 这个节点的逻辑是"依次尝试,直到成功为止"。
- 先试试厨房有没有剩菜(第一个子节点)
- 如果厨房空空如也(失败),那就去花园抓虫子(第二个子节点)
- 虫子也没有?那就啃树皮吧(第三个子节点)
- 只要有一个成功了,选择节点就满意地说:"搞定!"
**执行规则** 比如哥布林饿了,它会
``` 1. 先去厨房找剩菜
从左到右挨个试: 2. 厨房没有就去花园抓虫子
✅ 子节点成功 → "太好了!" → 选择节点成功 3. 还是没有就啃树皮
❌ 子节点失败 → "下一个!" → 继续尝试
⏳ 子节点运行中 → "等等..." → 选择节点也运行中
```
#### 2.2 顺序节点 - "完美主义者" 选择器会从左到右依次执行子节点,只要有一个成功了就停止,返回成功。如果所有子节点都失败了,它才返回失败。
**性格特点**:严格按计划执行,一步都不能错 这种模式在游戏AI中特别常用比如敌人的攻击选择优先使用技能技能冷却中就普通攻击连普通攻击都不行就移动到攻击范围内。
还是那只饿肚子的哥布林,但这次你决定做一顿大餐: #### 序列节点Sequence
这个节点的逻辑是"按顺序执行,全部成功才算成功"。
比如哥布林要做一顿饭:
1. 先洗手 1. 先洗手
2. 然后准备食材 2. 准备食材
3. 接着开火做饭 3. 开火做饭
4. 最后享用美食 4. 享用美食
顺序节点就像一个强迫症患者: 序列节点会严格按顺序执行,只有当前步骤成功了才会进行下一步。任何一步失败,整个序列就失败。
- 必须先洗手,洗不干净就不继续
- 洗手成功了,才能准备食材
- 食材准备好了,才能开火
- 任何一步失败,整个计划泡汤!
**执行规则** 这种模式适合那些有明确步骤的任务,比如开门(检查是否有钥匙 → 走到门前 → 使用钥匙 → 推开门)。
```
严格按顺序来:
✅ 子节点成功 → "很好,下一步!" → 继续执行
❌ 子节点失败 → "完蛋了!" → 顺序节点失败
⏳ 子节点运行中 → "慢慢来..." → 顺序节点等待
```
#### 2.3 行为节点 - "实干家" #### 动作节点Action
**性格特点**:话不多说,撸起袖子就是干 这些是真正执行具体任务的节点:
这是真正干活的节点,比如:
- "巡逻10秒钟" - "巡逻10秒钟"
- "攻击敌人" - "攻击敌人"
- "播放死亡动画" - "播放死亡动画"
行为节点就像一个靠谱的员工,给它一个任务,它会: 动作节点会立即开始执行任务,然后根据情况返回对应的状态。有些动作是瞬时的(比如播放音效),有些需要持续一段时间(比如移动到目标点)。
- 立即开始执行(返回"运行中"
- 完成后汇报结果("成功"或"失败"
- 有些任务需要时间,会持续返回"运行中"
#### 2.4 条件节点 - "侦察兵" #### 条件节点Condition
**性格特点**:眼观六路,耳听八方,专门负责收集情报 这些节点负责检查当前的环境状态:
条件节点就像哨兵,负责观察环境:
- "敌人在视野内吗?" - "敌人在视野内吗?"
- "血量低于30%吗?" - "血量低于30%吗?"
- "身上有钥匙吗?" - "身上有钥匙吗?"
它们动作很快,瞬间给出答案:要么"是"(成功),要么"不是"(失败),没有"也许" 条件节点通常执行很快,瞬间返回成功或失败,不会有"运行中"的状态
### 3. 一个完整的哥布林决策故事 ### 一个完整的例子
让我们看看一哥布林守卫的完整思考过程 现在我们把这些节点组合起来,看看一哥布林守卫的行为树
``` ```
哥布林行为树: 哥布林守卫行为树:
根节点(选择) 根节点(选择
├── 战斗分支(序) ├── 战斗分支(序
│ ├── 条件:发现敌人? │ ├── 条件:发现敌人?
│ ├── 行为:冲向敌人 │ ├── 动作:冲向敌人
│ └── 行为:攻击 │ └── 动作:攻击
├── 巡逻分支(序) ├── 巡逻分支(序
│ ├── 条件:在巡逻路径上? │ ├── 条件:在巡逻路径上?
│ └── 行为:继续巡逻 │ └── 动作:继续巡逻
└── 待机分支 └── 待机分支
└── 行为:原地等待 └── 动作:原地等待
``` ```
**执行过程** 执行过程是这样的
1. **第一轮思考** 1. **平时状态**
- 选择节点:"让我看看该做什么..." - 选择器首先尝试战斗分支
- 尝试战斗分支 → 检查"发现敌人?" → 没有敌人失败 - 检查"发现敌人?" → 没有敌人,条件失败
- 尝试巡逻分支 → 检查"在巡逻路径上?" → 是的(成功)→ 开始巡逻(运行中) - 尝试巡逻分支 → 检查"在巡逻路径上?" → 是的,开始巡逻
2. **第二轮思考**(巡逻进行中) 2. **发现敌人时**
- 选择节点:继续之前的决策 - 选择器重新开始评估
- 巡逻分支:巡逻还在进行中... - 战斗分支:检查"发现敌人?" → 有敌人!条件成功
- 执行"冲向敌人" → 成功后执行"攻击"
3. **第三轮思考**(突然发现敌人): 这就是行为树的核心思想:每一帧都从根节点重新开始评估,根据当前情况选择最合适的行为。
- 选择节点:重新评估
- 尝试战斗分支 → "发现敌人?" → 有敌人!(成功)→ 冲向敌人(运行中)
这就是行为树的魅力:每一帧都在重新评估,动态调整策略,就像一个真正在思考的智能体! ### 执行机制
### 4. 可视化流程图 - 让抽象变具体 行为树有个很重要的特点:它每一帧都会从根节点重新开始执行。
看完了哥布林的故事,让我们用更直观的方式来理解行为树的执行过程。
#### 4.1 一颗简单的行为树结构
![image](../image/maunal/flow.png) ![image](../image/maunal/flow.png)
就是我们刚才的哥布林决策树的可视化版本。每个方块代表一个节点,箭头表示执行流向 张图展示了我们刚才的哥布林行为树的结构
#### 4.2 执行流程的"心跳"
行为树就像一颗跳动的心脏每一帧通常是1/60秒都会从根节点开始"心跳"一次:
![image](../image/maunal/flow2.png) ![image](../image/maunal/flow2.png)
**执行程就像这样** 执行程就像这样:
1. **心跳开始** - 从根节点开始 1. 从根节点开始
2. **向下探索** - 根据节点类型决定如何执行子节点 2. 根据节点类型决定如何执行子节点
3. **状态回传** - 叶子节点结果层层向上传递 3. 叶子节点返回结果层层向上传递
4. **等待下次心跳** - 一帧结束,等待下一帧继续 4. 一帧结束,下一帧重新开始
这种"心跳式"的执行方式让AI能够 这种每帧重新评估的机制有几个好处
- 🔄 **实时响应**:每帧都重新评估环境 - 能够实时响应环境变化
- 🎯 **优先级明确**重要的行为总是先被考虑 - 优先级明确,重要的行为总是先被考虑
- 🔧 **易于调试**可以清楚看到每一步的决策过程 - 调试时可以清楚看到决策过程
- 🚀 **性能友好**只执行必要的节点,避免浪费 - 性能还不错,只执行必要的节点
> **小贴士**:想象行为树就像一个永不疲倦的大脑,每一瞬间都在问自己:"现在最应该做什么?"然后立即行动! 当然这种机制也有一些需要注意的地方。比如如果你的行为树很复杂每帧都完整执行一遍可能会有性能问题。不过对于大部分游戏AI来说这都不是问题。