文章目录
一、行为树的类型谱系
"行为树"(Behavior Tree)是一个宽泛的术语。在 NPC AI 和模拟器设计领域,常用的行为决策架构有以下几类,彼此并不互斥,通常组合使用。
1.1 概率行为树(Probabilistic Behavior Tree)
当前《大观园浮世录》使用的主要模型。
原理:每个节点是一个行为,每次决策掷一次随机数,根据概率区间落入对应行为。概率值可以是静态常量,也可以根据状态动态计算。
r = random()
if r < P1(state): 行为A
if r < P1+P2: 行为B
else: 行为C(兜底)
优点:实现简单,容易产生"自然感"的变化。
缺点:角色的行为是对自身状态的反应,缺少对他人行为的感知和响应。凤姐不知道探春上回合干了什么,只知道自己当前的 fear 值是多少。
1.2 效用行为树(Utility-Based Behavior Tree)
原理:为每个可能的行为计算一个"效用分数"(utility score),选择当前效用最高的行为执行。效用函数综合多个变量加权计算。
utility(贪腐) = 0.4 × (1 - fear) + 0.3 × wealth_deficit + 0.2 × prestige
utility(立威) = 0.5 × prestige_gap + 0.3 × morale_threat
execute( argmax(utilities) )
与概率树的区别:概率树是"掷骰子选行为",效用树是"算分数选最优行为"。效用树的角色行为更理性、更目标导向,适合模拟策略性人物(如凤姐)。
在红楼语境下:凤姐每回合会计算"贪更多的收益"与"被查的风险"之间的权衡,而不是随机地有时贪有时立威。
1.3 有限状态机(Finite State Machine, FSM)
原理:角色处于若干离散状态之一(如"潜伏期"、"扩张期"、"对抗期"、"溃败期"),状态之间有明确的转换条件。在某个状态内,行为是固定的或有限变化的。
State: NEUTRAL
→ if evidence > 2: 转入 HOSTILE 状态
→ if wealth < 50: 转入 ACCUMULATE 状态
State: HOSTILE
→ 每回合必定尝试查账
→ if auditSuccess >= 2: 转入 TRIUMPH 状态
与概率树的区别:FSM 的行为取决于所处状态,而非每回合独立掷骰。角色有"阶段感",前期和后期行为截然不同。
当前模拟器的问题:凤姐的 attitude_tan 字段其实是个 FSM 的雏形(neutral/ally/hostile),但它目前只影响探春的查账概率,并没有真正改变凤姐自身的行为模式。这是一个已有骨架但未充分激活的结构。
1.4 目标导向行动计划(Goal-Oriented Action Planning, GOAP)
原理:角色有明确的目标(Goal),以及一组带前置条件和效果的动作(Action)。AI 在运行时动态规划一条能从当前状态到达目标的行动链。
目标: 赎身出府(需要 wealth >= 220)
可用动作:
- 收集情报(+intel, 耗时)
- 举报凤姐(需要 intel > 1, +wealth)
- 日常侍奉(+loyalty, +wealth少量)
规划: 日常侍奉 → 收集情报 → 举报凤姐 → 赎身
适用场景:目标明确、动作有前置条件的角色。雪雁的"赎身"弧线非常适合 GOAP——她的每个行为都应该服务于这个终极目标。
1.5 反应式行为树(Reactive/Event-Driven Behavior Tree)
原理:角色不主动行动,而是对其他角色的行为或世界事件做出反应。事件作为触发器,驱动对应的响应行为。
当凤姐执行"贪腐"且leaked=true:
→ 探春: evidence += 0.5(反应)
→ 雪雁: intel += 0.3(反应,如果在场)
当宝玉情绪低落:
→ 晴雯: 概率触发"陪伴安慰"行为
→ 袭人: 概率触发"向王夫人报告"行为
这正是当前模拟器最欠缺的部分——角色几乎不对彼此的具体行为做出反应,只对彼此留下的数值痕迹(evidence、loyalty等)做出延迟反应。
1.6 行为树的类型对比
| 类型 | 决策基础 | 角色感知 | 适合人物类型 |
|---|---|---|---|
| 概率行为树 | 自身状态+随机 | 低(只感知数值) | 所有人物(基础层) |
| 效用行为树 | 多变量加权得分 | 中(感知多维状态) | 策略型:凤姐、探春 |
| 有限状态机 | 所处阶段 | 中(感知关键阈值) | 有明确阶段弧线的角色 |
| GOAP | 目标规划 | 中(感知距目标距离) | 目标驱动型:雪雁、袭人 |
| 反应式行为树 | 他者行为事件 | 高(感知他人行动) | 所有人物(关联层) |
真实可信的 NPC 系统通常是多层复合的:用 FSM 定义人物所处阶段,用效用树在阶段内选择最优行为,用反应式层响应他人行动。
二、当前模拟器的关联性断层诊断
2.1 问题的本质
当前《大观园浮世录 v4》的架构可以用一句话概括:
一组独立运行的概率状态机,共享同一张数值表格,但不互相观察。
每个角色在自己的决策函数(decideFeng()、decideMaids() 等)里独立运行,读取的是 G 对象中的数值,但这些数值是上一时刻的结果沉淀,而不是对方刚刚做了什么的实时感知。
角色之间的联系完全通过"数值中介"实现:
凤姐贪腐 → G.feng.ledger++ → 探春读取 ledger 值 → 决策
这中间没有直接的"我看到你做了这件事,我要回应"的机制。结果是每个角色的行为读起来像是平行的独立故事,而非一张相互缠绕的关系网。
2.2 具体断层清单
断层一:凤探博弈没有直接互动回合
凤姐的 decideFeng() 和探春的 decideTan() 各自独立执行,没有"对话帧"——不存在"探春这回合向凤姐当面对质,凤姐在同一回合必须选择回应策略"的机制。现实中,博弈的精髓恰恰在于当面的应对和反制,而非各自暗中行动后数值此消彼长。
断层二:宝玉与怡红院丫鬟的情感几乎单向
宝玉的好感度 bao.affinity.qw、bao.affinity.xr 存在于状态表里,但晴雯和袭人的行为几乎不因宝玉的即时行为而改变。宝玉今天情绪崩溃,晴雯不会特别去安慰;宝玉今天心情大好,袭人不会趁机提出姨娘的要求。情感关系是静态的好感数值,而不是动态的双向互动流。
断层三:黛玉的愁绪与宏观事件脱节
黛玉的 sadness 每天随机浮动,偶尔触发"宝玉挨打"等事件时才有显著波动。但她不会因为"探春刚刚成功查账,府中震动"而感到不安;不会因为"省亲消息传来,全府繁忙,无人顾及她"而愁绪大增。她的情绪是封闭的内循环,与政治层完全隔离。
断层四:王夫人的干政是被动的数值,不是主动的角色行为
王夫人的 supportFeng 和 suspectTan 字段存在,袭人的告密会触发 wfy.suspectTan = true,但王夫人自己没有独立的决策函数。她不会在某个时刻主动介入,召见凤姐训话,或者当着众人面表扬探春。她只是一个被动的修正系数,而非一个行为主体。
断层五:丫鬟之间没有横向互动
晴雯的遭遇不影响紫鹃的情绪;袭人的告密不影响麝月的处境;雪雁赎身成功不影响春纤的忠诚(甚至不影响任何人)。原著中丫鬟群像的精彩之处在于横向的连带与对比,而模拟器中她们六人是六条平行的独立折线。
断层六:事件没有人格化响应
大事件触发后,会直接修改数值(deficit+、turmoil+ 等),但没有触发相关角色的即时响应行为。"宝玉挨打"事件发生后,黛玉不会立刻哭倒,贾母不会立刻介入,凤姐不会立刻趁乱——他们只在下一个常规回合里继续执行各自的独立决策流程。
2.3 断层的根源:缺少三种机制
机制一:行为事件总线(Event Bus)
每当一个角色执行有意义的行为,应当向全局广播一个事件,其他角色可以订阅并即时响应。
// 凤姐贪腐时广播
emit('FENG_CORRUPT', { amount: 45, leaked: true })
// 探春订阅
on('FENG_CORRUPT', ({ leaked }) => {
if (leaked) tan.evidence += 0.5
if (tan.attitude === 'hostile') tan.reactNow = true // 下回合优先查账
})
// 紫鹃订阅
on('FENG_CORRUPT', () => {
if (Math.random() < 0.3) zj.intel += 0.2 // 潇湘馆有人听到了风声
})
机制二:对话/冲突帧(Confrontation Frame)
当两个角色的关系进入 hostile 状态,且都有精力时,应触发一个"共同回合",双方在同一帧内互动,结果取决于双方的当前状态对比,而非各自的独立随机数。
if (feng.attitude === 'hostile' && tan.attitude === 'hostile'
&& feng.stamina > 0 && tan.stamina > 0) {
runConfrontation(feng, tan)
// 双方各出一张牌,综合计算胜负
}
机制三:情感传播网络(Emotional Contagion)
情绪和消息应该在关系网络中传播,而不是每个角色孤立地随机浮动。
// 宝玉情绪崩溃时
if (bao.mood < 20) {
propagate('BAO_DISTRESS', {
qw: { loyalty: +3, triggerComfort: 0.6 }, // 晴雯更想护主
xr: { spyChance: +0.2 }, // 袭人更想去告密
dai: { sadness: +8 }, // 黛玉感应到了
})
}
三、改进方向的优先级建议
综合以上分析,关联性改进按投入产出比排序如下:
第一优先:为主要角色添加行为事件广播
工作量小,效果立竿见影。凤姐的贪腐、探春的查账、宝玉的情绪事件各自广播,其他角色订阅响应。这一改动能立刻让日志变得"有因有果"。
第二优先:激活王夫人为真正的行为主体
给王夫人添加 decideWfy() 函数,让她根据凤姐威望、探春改革进度、袭人告密次数做出主动行为(召见、训斥、赐福),而不只是一个修正系数。
第三优先:将凤探关系升级为 FSM + 对话帧
将 attitude 字段真正激活为状态机,在 hostile 状态下触发对抗帧,让两人在同一回合内博弈,而不是各自行动后对数值做加减。
第四优先:添加情感传播规则
为宝玉的情绪、黛玉的健康、晴雯被撵等高影响力事件添加向外传播的情感波纹,使大事件的后果能在多个角色间漾开。
第五优先:将雪雁、袭人升级为 GOAP 模型
两人各有明确的人生目标(赎身、成为姨娘),所有行为都应服务于这个目标。GOAP 能让她们的行动逻辑更连贯,而不是每回合随机选择"告密还是侍奉"。
四、小结
当前模拟器的核心问题不是"缺少更好的行为树类型",而是缺少角色之间的信息流通机制。无论使用什么类型的行为树,如果每个角色只能感知自身的数值状态,而无法感知他人的即时行为,那么他们必然是"各做各的"。
真正有生命力的多角色模拟,需要在决策层之下建立一张事件-响应网络:角色做出行为,行为产生事件,事件传播给相关角色,相关角色据此调整下一步决策。这个循环的密度和复杂度,决定了模拟世界的"活"的程度。
《红楼梦》原著之所以震撼人心,正是因为书中每一个角色的命运都与他人深度缠绕——一个丫鬟的赎身,牵扯着管家的账目;一个公子的痴病,映照着才女的泪水。模拟器若要还原这种缠绕感,事件总线和情感传播网络是不可或缺的基础设施。
文档生成时间:2026-03-23 04:19 CST
评论