by AKara 2010-12-09 @ http://blog.csdn.net/akara @ akarachen(at)gmail.com @weibo.com/akaras

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

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

虽说Next-Gen AI,但距其原型提出已有约10年时间,而Halo系列(HFSM like),
Spore,Crysis 2,Red Dead Redemption等早已用行为树作为它们的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 Fall On All Node: 所有False才返回False,否则返回True。
    Parallel Succeed On All Node: 所有True才返回True,否则返回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 Node提供每次执行不同First True Child Node的功能。
  Weight Random Probability Node提供每次挑选唯一一个Node的功能。
  Weight Random Sequence Node则提供每次不同的迭代顺序。
  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。)
 
  更强大的是可以加入StimulusImpulse,通过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,长远来说非常有价值。

AI 行为树的更多相关文章

  1. UE4中的AI行为树简单介绍

    UE4引擎中可以实现简单AI的方式有很多,行为树是其中比较常用也很实用的AI控制方式,在官网的学习文档中也有最简单的目标跟踪AI操作教程,笔者在这里只作简单介绍. AIController->和 ...

  2. AI行为树的工作原理

    很久没写博客了,最近在项目刚部署到测试服,需要进行压测,老大相当专业的用了行为树来组织压测机器人的代码,这段时间陆陆续续在网上看了不少关于行为树的文章,其中有一篇我觉得写得非常到位,它原文是英文,链接 ...

  3. [Unity插件]AI行为树使用总结

    参考链接: https://blog.csdn.net/linxinfa/article/details/72937709 https://blog.csdn.net/wanghaodiablo/ar ...

  4. 游戏AI之决策结构—有限状态机/行为树(2)

    目录 有限状态机 行为树 控制节点 条件节点 行为节点 装饰节点 总结 额外/细节/优化 游戏AI的决策部分是比较重要的部分,游戏程序的老前辈们留下了两种经过考验的用于AI决策的结构: 有限状态机 行 ...

  5. 【转】B-树和B+树的应用:数据搜索和数据库索引

    B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树: ⑴树中每个结点至多有m 棵子树: ⑵若根结点不是叶子 ...

  6. 数据结构 B-树和B+树的应用:数据搜索和数据库索引

    B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树:⑴树中每个结点至多有m 棵子树:⑵若根结点不是叶子结点 ...

  7. UE4简单AI

    首先做个小小的声明把,由于俺之前也没接触过AI ,所以有一些专业的词汇可能翻译存在各种问题,如果你发现的话,还是希望能够提出来哦,我们一起进步. 记住配合视频食用更佳哦~ 视频连接:http://ww ...

  8. B-树和B+树的应用:数据搜索和数据库索引

    B-树和B+树的应用:数据搜索和数据库索引  B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树:⑴树中每 ...

  9. (转)B-树和B+树的应用:数据搜索和数据库索引

    B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树: ⑴树中每个结点至多有m 棵子树: ⑵若根结点不是叶子 ...

随机推荐

  1. c++ 常用数据接口 set

    #include <set> #include <iostream> #include <string> int main(void) { std::set< ...

  2. [转载]App.Config详解及读写操作

    App.Config详解 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而不必重编译应用程序.配置文件的根节点是c ...

  3. 01-04-03【Nhibernate (版本3.3.1.4000) 出入江湖】Criteria API关联查询

    Criteria API关联查询 如果说HQL查询还有需要了解点SQL语法知识,并不是完全彻底面向对象查询, 那么Criterial API就是完全面向对象的查询方式. public IList< ...

  4. Unity3D TestTool Part _1

    一直想看看Unity3d官方推出的UnityTestTools的测试插件,今天有空尝试了一下. 一.Quick Start 1. create a plane position which trans ...

  5. GOOGLE搜索秘籍完全公开

    一,GOOGLE简介 Google(www.google.com)是一个搜索引擎,由两个斯坦福大学博士生Larry Page与Sergey Brin于1998年9月发明,Google Inc. 于19 ...

  6. Android 用Activity的onTouchEvent来监听滑动手势

    package com.example.activityOnTouchEvent; import android.app.Activity; import android.os.Bundle; imp ...

  7. Oracle 学习笔记(三)

    1.插入有日期的表,使用 to_date 函数 to_date('1992-12-07', 'yyyy-mm-dd'); 2.使用update更新语句的时候,既可以使用表达式或者数值直接修改数据,也可 ...

  8. Bash的脚本参数

    $0:脚本名字.此变量包含地址,可以使用basename $0获得脚本名称.$1:第一个参数$2,$3,$4,$5,…一次类推. $# 传递到脚本的参数个数$* 以一个单字符串显示所有向脚本传递的参数 ...

  9. Openfire 服务端在Eclipse上部署

    http://blog.csdn.net/chexitianxia/article/details/9371169 结合: http://blog.csdn.net/ares1201/article/ ...

  10. lintcode:Coins in a Line 硬币排成线

    题目 硬币排成线 有 n 个硬币排成一条线.两个参赛者轮流从右边依次拿走 1 或 2 个硬币,直到没有硬币为止.拿到最后一枚硬币的人获胜. 请判定 第一个玩家 是输还是赢? 样例 n = 1, 返回  ...