【转载】行为树(Behavior Tree)

使用行为树(Behavior Tree)实现游戏AI
by AKara 2010-12-09 @ http://blog.csdn.net/akara @ [email protected]

———————————————————————

谈到游戏AI,很明显智能体拥有的知识条目越多,便显得更智能,但维护
庞大数量的知识条目是个噩梦:使用有限状态机(FSM),分层有限状态机(HFSM),
决策树(Decision Tree)来实现游戏AI总有那么些不顺意。

试试Next-Gen AI的行为树(Behavior Tree)吧。

虽说Next-Gen AI,但距其原型提出已有约10年时间,而微软Halo系列估计
已用了超过8年了,Spore和一些著名游戏也早已使用行为树作为它们的AI结构。
如从未接触,那wikipedia(http://en.wikipedia.org/wiki/Behavior_Trees)
绝对是入门好资料。

———————————————————————

先贴本文最具价值图(配色可花了不少时间)

为显美观:BT被横放,Node层次被刻意减少,Dec被刻意安插,Cond被刻意捏造。
PS:其实真正的高效的Node Group剔除应多加一层Sequence Node。

———————————————————————

行为树(Behavior Tree)具有如下的特性:

它只有4大类型的Node:
* Composite Node
* Decorator Node
* Condition Node
* Action Node

任何Node被执行后,必须向其Parent Node报告执行结果:成功 / 失败。
这简单的成功 / 失败汇报原则被很巧妙地用于控制整棵树的决策方向。

———————————————————————

先看Composite Node,其实它按复合性质还可以细分为3种:
* Selector Node
当执行本类型Node时,它将从begin到end迭代执行自己的Child Node:
如遇到一个Child Node执行后返回True,那停止迭代,
本Node向自己的Parent Node也返回True;否则所有Child Node都返回False,
那本Node向自己的Parent Node返回False。

* Sequence Node
当执行本类型Node时,它将从begin到end迭代执行自己的Child Node:
如遇到一个Child Node执行后返回False,那停止迭代,
本Node向自己的Parent Node也返回False;否则所有Child Node都返回True,
那本Node向自己的Parent Node返回True。

* Parallel Node
并发执行它的所有Child Node。
而向Parent Node返回的值和Parallel Node所采取的具体策略相关:
Parallel Selector Node: 一False则返回False,全True才返回True。
Parallel Sequence Node: 一True则返回True,全False才返回False。
Parallel Hybird Node: 指定数量的Child Node返回True或False后才决定结果。

Parallel Node提供了并发,提高性能。
不需要像Selector/Sequence那样预判哪个Child Node应摆前,哪个应摆后,
常见情况是:
(1)用于并行多棵Action子树。
(2)在Parallel Node下挂一棵子树,并挂上多个Condition Node,
以提供实时性和性能。
Parallel Node增加性能和方便性的同时,也增加实现和维护复杂度。

PS:上面的Selector/Sequence准确来说是Liner Selector/Liner Sequence。
AI术语中称为strictly-order:按既定先后顺序迭代。

Selector和Sequence可以进一步提供非线性迭代的加权随机变种。
Weight Random Selector提供每次执行不同的First True Child Node的可能。
Weight Random Sequence则提供每次不同的迭代顺序。
AI术语中称为partial-order,能使AI避免总出现可预期的结果。

———————————————————————

再看Decorator Node,它的功能正如它的字面意思:它将它的Child Node执行
后返回的结果值做额外处理后,再返回给它的Parent Node。很有些AOP的味道。

比如Decorator Not/Decorator FailUtil/Decorator Counter/Decorator Time…
更geek的有Decorator Log/Decorator Ani/Decorator Nothing…

———————————————————————

然后是很直白的Condition Node,它仅当满足Condition时返回True。

———————————————————————

最后看Action Node,它完成具体的一次(或一个step)的行为,视需求返回值。
而当行为需要分step/Node间进行时,可引入Blackboard进行简单数据交互。

———————————————————————

整棵行为树中,只有Condition Node和Action Node才能成为Leaf Node,而也
只有Leaf Node才是需要特别定制的Node;Composite Node和Decorator Node均
用于控制行为树中的决策走向。(所以有些资料中也统称Condition Node和Action
Node为Behavior Node,而Composite Node和Decorator Node为Decider Node。)

更强大的是可以加入Stimulus和Impulse,通过Precondition来判断masks开关。

通过上述的各种Nodes几乎可以实现所有的决策控制:if, while, and, or,
not, counter, time, random, weight random, util…

———————————————————————

总的来说,行为树具有如下几种优点,确实是实现AI框架的利器,甚至是一种
通用的可维护的复杂流程管理利器:

> 静态性
越复杂的功能越需要简单的基础,否则最后连自己都玩不过来。

静态是使用行为树需要非常着重的一个要点:即使系统需要某些”动态”性。

其实诸如Stimulus这类动态安插的Node看似强大,
但却破坏了本来易于理解的静态性,弊大于利。
Halo3相对于Halo2对BT AI的一个改进就是去除Stimulus的动态性。
取而代之的做法是使用Behavior Masks,Encounter Attitude,Inhibitions。
原则就是保持全部Node静态,只是根据事件和环境来检查是否启用Node。

静态性直接带来的好处就是整棵树的规划无需再运行时动态调整,为很多优化
和预编辑都带来方便。

> 直观性
行为树可以方便地把复杂的AI知识条目组织得非常直观。
默认的Composite Node的从begin往end的Child Node迭代方式就像是处理一个
预设优先策略队列,也非常符合人类的正常思考模式:先最优再次优。

行为树编辑器对优秀的程序员来说也是唾手可得。

> 复用性
各种Node,包括Leaf Node,可复用性都极高。
实现NPC AI的个性区别甚至可以通过在一棵共用的行为树上不同的位置来
安插Impulse来达到目的。

当然,当NPC需要一个完全不同的大脑,比如70级大BOSS,
与其绞尽脑汁在一棵公用BT安插Impulse,不如重头设计一棵专属BT。

> 扩展性
虽然上述Node之间的组合和搭配使用几乎覆盖所有AI需求。
但也可以容易地为项目量身定做新的Composite Node或Decorator Node。
还可以积累一个项目相关的Node Lib,长远来说非常有价值。

--------------------------------本人补充---------------------------------------

每个节点都应该有以下三种状态:
Running,
Success,
Failed

Running状态用于表明该节点的结果不能立刻获知,比如游戏中的角色进行“向目标移动”

这个动作,很显然这个动作不能在这一帧中立刻完成,当行为树运行到此节点时,并不能

获知是success或者failed,于是返回running,表示该节点正在运行中,并记录此节点

的位置,下一帧运行到此节点的父节点时,则从此节点继续运行,跳过之前的节点。

时间: 2024-12-28 01:22:28

【转载】行为树(Behavior Tree)的相关文章

使用行为树(Behavior Tree)实现游戏AI

原地址:http://blog.csdn.net/akara/article/details/6084786 [原创]使用行为树(Behavior Tree)实现游戏AIby AKara 2010-12-09 @ http://blog.csdn.net/akara @ akarachen(at)gmail.com @weibo.com/akaras 谈到游戏AI,很明显智能体拥有的知识条目越多,便显得更智能,但维护庞大数量的知识条目是个噩梦:使用有限状态机(FSM),分层有限状态机(HFSM)

使用行为树(Behavior Tree)实现网游奖励掉落系统

原地址:http://blog.csdn.net/akara/article/details/6165421 [原创]使用行为树(Behavior Tree)实现网游奖励掉落系统by AKara 2011-01-24 @ http://blog.csdn.net/akara @ akarachen(at)gmail.com @weibo.com/akaras 奖励/掉落系统,涵盖物品,经验,金钱等网游中可直接给予玩家的元素.一个简单,直观,可扩展的掉落系统对网游中的产出控制起非常重要的作用. 奖

[转载]伸展树(一)之 图文解析 和 C语言的实现

概要 本章介绍伸展树.它和"二叉查找树"和"AVL树"一样,都是特殊的二叉树.在了解了"二叉查找树"和"AVL树"之后,学习伸展树是一件相当容易的事情.和以往一样,本文会先对伸展树的理论知识进行简单介绍,然后给出C语言的实现.后序再分别给出C++和Java版本的实现:这3种实现方式的原理都一样,选择其中之一进行了解即可.若文章有错误或不足的地方,希望您能不吝指出! 目录 1. 伸展树的介绍 2. 伸展树的C实现 3. 伸展树的

线段树(segment tree)

1.概述 线段树,也叫区间树,是一个完全二叉树,它在各个节点保存一条线段(即"子数组"),因而常用于解决数列维护问题,基本能保证每个操作的复杂度为O(lgN). 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b].因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度. 使用线段树可以

Leetcode 树 Symmetric Tree

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Symmetric Tree Total Accepted: 13991 Total Submissions: 44240 Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For example, this binary tree is symmet

Leetcode 树 Same Tree

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Same Tree Total Accepted: 15922 Total Submissions: 38418 Given two binary trees, write a function to check if they are equal or not. Two binary trees are considered equal if they are structurally

Leetcode 树 Binary Tree Level Order Traversal II

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Binary Tree Level Order Traversal II Total Accepted: 10080 Total Submissions: 32610 Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, l

Leetcode 树 Binary Tree Zigzag Level Order Traversal

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Binary Tree Zigzag Level Order Traversal Total Accepted: 8678 Total Submissions: 33047My Submissions Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from le

线段树(Segment Tree)(转)

原文链接:线段树(Segment Tree) 1.概述 线段树,也叫区间树,是一个完全二叉树,它在各个节点保存一条线段(即“子数组”),因而常用于解决数列维护问题,基本能保证每个操作的复杂度为O(lgN). 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b].因此线段树是平衡二叉树,最后的子节点数目为N,即