type
status
date
slug
summary
tags
category
icon
password
fullWidth
fullWidth
行为树入门推荐阅读这篇文章:行为树介绍 - Robohub
itch.io传送门(WebGL平台):PacManDemo

行为树定义

行为树(Behavior Tree)是一个抽象概念,具有以下特征:
  1. 行为树是树:从根节点开始,按特定顺序遍历,直到达到最终状态(成功或失败)。
  1. 叶节点是可执行行为:叶子结点会进行具体的操作,返回状态信息(成功、失败或运行中),叶子节点是将行为树连接到特定应用程序的较低级别代码的位置。
  1. 非叶节点控制数遍历:非叶节点接收其子节点的结果状态,用特定规则来指示接下来应该执行哪个节点。
行为树诞生于游戏领域,用于定义非玩家角色(NPC)的行为,Unreal Engine和Unity都有用于传播工作行为树的专用工具。后来行为树进入了机器人领域,有兴趣可以阅读这篇论文:[1709.00084] Behavior Trees in Robotics and AI: An Introduction

流程行为树

如玩法、任务行为树,像剧本一样线性推进,玩家每完成一个操作(如对话、拾取物品),行为树才推进到下一个节点。
  • 单次执行:只运行一次,完成后行为树结束
  • 同步性:行为树状态是实时的,与游戏表现同步

决策行为树

如NPC出牌行为树,以固定频率(如每帧)重新评估整棵树,每次都动态选择最优分支,比如AI根据战场变化切换进攻或逃跑。
  • 轮询执行:从根节点开始反复执行,每次返回的状态可能不同
  • 异步性:决策过程在极短时间内完成,而游戏表现可能存在延迟

节点类型

notion image
行为树的节点类型可分为两大类:
  1. 控制节点:也称内部节点,根据子节点的状态和特定规则定义如何遍历行为树。序列(Sequence)选择(Selector)和 平行(Parallel)节点可以有多个子节点,装饰(Decorator)节点只有一个子节点,并使用自定义策略,如重复(Repeat)始终失败(AlwaysFailure)取反(Invert),来修改其行为。
    1. 序列(Sequence)
      1. Sequnce按顺序执行子项,直到一个子项返回 Failure 或所有子项返回 Success
        Sequnce按顺序执行子项,直到一个子项返回 Failure 或所有子项返回 Success
    2. 回退(Fallback)/选择(Selector)
      1. Fallback按顺序执行子节点,直到其中一个子节点返回 Success 或所有子节点返回 Failure
        Fallback按顺序执行子节点,直到其中一个子节点返回 Success 或所有子节点返回 Failure
    3. 平行(Parallel)
      1. Parallel的每个子节点将按顺序单独更新,至少有M个子节点(介于1到N)成功时,Parallel返回Success,当所有子节点都失败时,Parallel返回Failure
        Parallel的每个子节点将按顺序单独更新,至少有M个子节点(介于1到N)成功时,Parallel返回Success,当所有子节点都失败时,Parallel返回Failure
    4. 装饰(Decorator)
      1. Decorator使用自定义策略修改单个子节点,例如,Invert会将Success更改为Failure
        Decorator使用自定义策略修改单个子节点,例如,Invert会将Success更改为Failure
  1. 执行节点:是行为树的叶子节点,有行为(Action)条件(Condition)两类。

执行过程

行为树在时钟周期(Tick)的离散更新步骤中执行,子节点根据树的构造方式地柜执行,会向父节点返回状态,可以是成功(Success)失败(Failure)执行中(Running)
🐈‍⬛
更复杂的行为树节点状态
下面通过一个机器人搜索物体的例子来理解行为树的执行过程。
notion image
如果只存在一个地点A,那么行为树很简单,到A处,找到物体。
notion image
如果在执行行动前先进行条件检查:检测机器人是否已经在A处,如果在就不执行去A处的动作,直接返回成功状态;如果不在,才执行去A处的动作。
notion image
如果机器人要寻找多个感兴趣的对象,可引入更上级的回退(Fallback)节点。
notion image
如果考虑在一个地点同时寻找多个对象,而不是单个对象,又可以进行如下修改。
notion image

黑板

为了存储可以被多个结点访问的共享信息,引入黑板(blackboard)的概念——一个可以被所有结点读写公共存储区
notion image

行为树和有限状态机

行为树和有限状态机在模块化反应性之间存在权衡。一般来说,行为树更易组合和修改,而有限状态机在设计反应式行为方面更有优势。

行为树的优点

以下案例是机器人移动到一个物体上,关闭夹具抓取物体,再移动回起始位置。
行为树(左)和有限状态机(右)
行为树(左)和有限状态机(右)
如果想修改此行为,在抓取物体之前检查有效性,并进行纠正,如果使用行为树,可以直接插入一个子树,而有限状态机必须重新连接多个转换,由此可见行为树非常适合模块化。
notion image

行为树的缺点

对于反应式行为,比如机器人低电量时需要马上回到电源处。
如果使用行为树来实现会非常麻烦,需要在任意任务的子树中支持充电行为。
notion image
但对于状态机实现起来很简单,只需要从所有其它动作连线到充电动作即可。
notion image
分层有限状态机(FSM)建立高级状态以简化状态间的转换,比如定义一个Nominal的超级状态,表示正常运转和充电两种明确的模式。
notion image

应用场景

行为树更好还是有限状态机更好需要看具体要解决的问题。有限状态机更方便管理高优先级的操作行为(比如机器人处于正常状态还是充电状态),行为树更适合定义复杂的行为,比如处理错误恢复。实践中,混合使用两者可能会是更好的选择。
两全其美:高级模式切换由有限状态机处理,特定模式的行为由行为树管理
两全其美:高级模式切换由有限状态机处理,特定模式的行为由行为树管理

框架搭建

此处依据原初的行为树定义搭建代码框架,而不同项目会对原初的行为树做一些魔改以适配业务需求,导致定义和实现有所差异。以下是某项目客户端的行为树模块的框架:
notion image

节点基类

行为树节点基类(BTNode)

行为树中所有节点的基类,包含Execute接口,返回节点状态NodeStatus

控制节点基类(ControlNode)

继承自BTNode,可以有子节点。

执行节点基类(ExecutionNode)

继承自BTNode,不能有子节点。

各类控制节点

序列(Sequence)

重写Execute方法,按顺序执行子节点。

并行(Parallel)

初始化时需要传入成功所需的最小成功子节点数successThreshold,重写Execute方法,依次执行子节点,当满足最小成功子节点数时直接返回Success,否则返回RunningFailure

选择(Selector)

按顺序执行子节点,全部失败才返回Failure

装饰(Decorator)

装饰节点只能有一个子节点,需要提供判断是否有子节点的HasChild属性和设置子节点的SetChild接口。
实现几种常用的装饰节点:
  • 反转(Invert):反转节点的执行结果
  • 重复(Repeat):重复执行子节点指定次数
  • 总是成功(AlwaysSuccess):无论子节点结果如何都返回成功
  • 总是失败(AlwaysFailure):无论子节点结果如何都返回失败

各类执行节点

条件(Condition)

通过传入的Func<bool>委托来判断某个条件是否成立,返回SuccessFailure

行为(Action)

通过传入的Func<NodeStatus>委托执行具体行为,直接返回行为执行结果SuccessFailureRunning

执行器(Runner)

从根节点开始运行行为树,初始化时必须传入根节点root

构建器(Builder)

链式调用的方式方便地构建行为树结构,提供各类节点的构造方法,End()Build()接口。
  • End():结束当前控制节点的构建,从节点栈中弹出当前控制节点,必须与对应控制节点配对使用,如果嵌套多层控制节点,也需要对应数量的End()与之配对。
  • Build():完成行为树的构建并返回一个可执行的BTRunner

*黑板(Blackboard)

也可以引入黑板(Blackboard)作为行为树节点之间数据共享的媒介(对于体量较小的游戏,可直接将共享的数据存在GameManager中,或者使用其他的运行时数据管理类)。
以下是黑板的一种可能实现形式,使用键值对存储数据,并提供基于泛型的增删查改功能。

使用案例

使用以上行为树框架制作吃豆人游戏的怪物AI。

怪物模拟

静态类GhostSimulator中定义了各种条件行为
  • 条件:
    • 玩家是否处于能量豆状态
    • 玩家是否在范围内
  • 行为:
    • 巡逻:沿着巡逻点缓慢移动
    • 追击:朝玩家所在的方向快速接近玩家
    • 逃跑:朝玩家所在方向的反方向快速逃离玩家

行为树构建

提供BuildBehaviorTree的方法,将怪物的行为逻辑硬编码到代码中。

AI怪物行为

怪物逃跑
怪物逃跑
怪物由追转逃
怪物由追转逃
 
怪物追击玩家
怪物追击玩家
怪物由逃转追
怪物由逃转追
Relate Posts
【独立游戏】Blizzard Syndrome
Lazy loaded image
【独立游戏】MeloGo
Lazy loaded image
【独立游戏】Grey School Plot
Lazy loaded image
【学校项目】智能家居数字人管家
Lazy loaded image
【毕业设计】基于GarmentCode的参数化和组件化服装版片生成
Lazy loaded image
【Built-in渲染】3D卡通角色NPR前向渲染和物理模拟
Lazy loaded image
【游戏算法】游戏AI行为决策-目标导向行为规划(GOAP)通用框架【游戏算法】游戏AI行为决策-分层任务网络(HTN)的简单应用
Loading...
Latest posts
【虚幻Slate】虚幻编辑器扩展之开发一个AVG游戏剧情编辑器
2025-12-25
【TypeScript】性能记录框架和装饰器
2025-12-12
【Built-in渲染】绘画色彩理论在卡渲后处理中的应用
2025-12-12
【散文随笔】我的高中生活(二)
2025-12-12
【散文随笔】我的高中生活(一)
2025-12-12
【兴趣爱好】音乐创作存档
2025-12-12