Behavior Designer插件(下)

一、重点提示

1、行为树是一种逻辑工具,对工具的学习方法肯定是实用优先。
特地说这个是因为Behavior Designer提供的功能其实比我们要用的多。作为使用者,务必记住要先把基本功能搞清楚,在初期那些不必要的高级功能只会把我们的思路搞乱而已。设计AI本身已经是很烧脑的工作,不建议使用一些很不直观的修饰器和组合器给自己添乱。而且基本功能已经足够我们组合出非常复杂而强大的行为树了。
2、行为树中的节点,会在某一帧中被调用,然后立即得到一个结果:成功Success、失败Failure、运行中Running,只能取三者其一。然后组合器和修饰器会根据返回值进行下一步,这是行为树的基本逻辑。3、节点不是多线程并行的,被调用的节点都必须迅速执行完毕并返回Running、Success或者Failure。所有事件就算是同时发生,也总有先后之分。

二、组合器的详细介绍

注:本段先略读一遍,然后下一段咱们会做实验,边实验边阅读效果更佳。

Sequence 串行的AND

Sequence 类似于编程语言中的"&&"符号,它从左到右,每帧只执行一个子节点。
1、如果当前子节点返回Running,那么Sequence也返回Running。下一帧继续执行当前这个子节点。
2、如果当前子节点返回失败,那么Sequence节点本身返回失败。
3、如果当前子节点返回成功,如果还有下一个子节点,那么Sequence本身返回Running,下一帧会切换到下一个子节点; 如果所有子节点都完毕了,则Sequence节点返回成功,整个节点结束。

Selector 串行的OR

Selector与Sequence执行顺序相同,逻辑正巧是“||”的逻辑。它也是从左到右,每帧只执行一个子节点。
1、如果当前子节点返回Running,那么Selector也返回Running。下一帧继续执行当前这个子节点。
2、如果当前子节点返回失败,那么Selector节点本身返回Running,下一帧执行下一个子节点;如果所有子节点都失败了,就返回失败。
3、如果当前子节点返回成功,那么Selector返回成功。

Parallel 并行的AND

Parallel 从返回值来看它是 “&&” 逻辑。与Sequence的区别是,在每一桢,它都执行所有子节点一次
1、所有子节点都Running,那么Parallel节点也返回Running。
2、有任何一个节点返回失败,那么Parallel立刻结束,返回失败。还处于Running的子节点也会终止(从界面上可以看出,正在Running的被假设为失败)。
3、有任何一个节点返回成功,那么该子节点下一帧就不会被调用了,但是Parallel本身仍然返回Running,直到所有子节点都返回成功,Parallel才返回成功。

Parallel Selector 并行的OR

Parallel Selector 从返回值来看是 “||” 逻辑。它是并行的,每一桢执行所有子节点一次
1、所有子节点都Running,那么Parallel Selector节点也返回Running。
2、有任何一个节点返回失败,那么Parallel Selector 本身返回Running,直到所有子节点都失败了,它才返回失败。
3、有任何一个节点返回成功,Parallel Selector 直接返回成功。

好的,我们解释了四种最基本的节点,只需它们就足够组成行为树的骨架。下图是Composites全图,我给它们分了组,前面介绍的就是最上面一排基本组。

image.png

其它节点就容易了,我们继续看看:

Random Sequence 变体的Sequence(串行)

Sequence是从左到右串行,Random Sequence 也是串行完全一样,只是它从还没执行过的N个子节点中随机挑选一个执行。

Priority Selector, Random Selector 变体的Selector(串行)

这二者是Selector的变体,也都是串行。分别是根据优先级挑选、随机挑选、自定义挑选顺序。
★ 再强调一下,串行情况下,如果有节点还在running,那么肯定先执行running的节点。“挑选”的意思是说,在没有running的节点时,从还没执行过的节点中,根据规则挑出一个。

Selector Evaluator, Utility Selector 特殊顺序的Selector

这两种类型的特殊之处在于:在每一帧,都要重新计算子节点的优先级或者效用,就算节点正在running,也有可能因为优先级变化而切换节点。它们既不是并行也不是串行。Utility Selector 是一种选择器,它是基于“Utility”也就是“效用”进行选择,用在《模拟人生》这种游戏中会非常有效,就是当你面对吃法、睡觉、上厕所这三件事时,你选效用最大的那一件事去做即可,而且如果有必要可以随时终止当前正在做的事情。Selector Evaluator 涉及到优先级的问题,暂且不表。

三、组合器和返回值实验+详解

前面的讲解过于抽象,咱们可以做下面这样的一个行为树,挂在任意一个GameObject上面,直观感受各种组合器的特性:


image.png

说明:新建GameObject到场景中,并为它创建一个行为树如上图。四个动作节点是Wait节点,在行为树的Inspector窗口里,把Wait节点的等待时间分别改为2、1、2、3秒。然后执行效果如下:


image.gif

通过一些简答的例子,瞬间就对组合器功能有了直观认识。之后再看前面的介绍,就可以掌握这些组合器的用法了。
image.jpeg

小技巧:用Replace功能即可快速替换节点类型。

还有修饰器的作用就不再详细表述了,大概列举如下:
1.Inverter:条件判断或动作的返回结果取反,成功变失败,失败变成功,Running不变。
2.Reapter:循环执行,可以调节循环次数等参数。
3.Return Failure:返回值无论成功或失败都返回失败,但Running还是Running。
4.Return Success:同上,相反。Until Failure:循环直到失败,换句话说如果成功就再次执行子节点。5.Until Success:同上,相反。

四、变量应当保存在行为树中,还是角色脚本中?

思考这样一个问题:如果我们不用Bahavior Designer插件,那么脚本中也有各种角色相关的参数和变量,而如果用了插件,那么也可以把变量放在行为树里面,就好比之前用过的SharedTransform等等变量。选择多了麻烦也多,到底把变量放在角色脚本中还是行为树里面呢?好在有办法可以在行为树中访问角色的变量,这样一来还是比较方便的。例如,AI角色开火动作的脚本:

public class FireAction : Action{
    // The transform that the object is moving towards
    CharacterData chaData;

    public override void OnAwake()
    {
        chaData = gameObject.GetComponent<CharacterData>();
    }}

如意上面的CharacterData chaData,这个就是我的NPC角色身上的一个脚本组件。用上面的写法,就可以在动作脚本中访问其他脚本的变量或者调用角色的函数了:


// 还是FireAction的OnUpdate函数
    public override TaskStatus OnUpdate()
    {  // 调用角色的方法
        chaData.Fire();
        return TaskStatus.Success;
    }

到底哪些函数和变量放在角色脚本中,哪些函数和变量放在行为树的动作脚本中?这是一个工程问题了,没有统一的方法。
个人建议:所有角色通用的变量和方法,放在角色脚本中。因为即使不用Behavior Designer插件,这些变量和方法也是有用的。而只用于AI的变量,放在行为树的Variables里面即可,由专门负责AI设计的人员维护。例如:角色移动速度、开火CD时间,都是角色本身的变量。而发现敌人的transform、距离敌人的距离,如果只在AI逻辑中用到,就应该放在行为树中。
★ 也有办法在角色脚本中访问行为树的变量,可以查阅官方文档和资料。但是我们尽可能避免这种用法,这种反向耦合对项目整洁不利。

五、复杂一些的行为树实战

为了综合运用所有行为树的知识,我又做了一个复杂的例子。我们的目标是在之前的例子的基础上,给AI增加如下功能:

1、灵活利用建筑进行防御。当玩家从右侧接近,则走到预定地点1防御;如果玩家从左侧接近,则走到预定地点2防御;如果玩家从中间接近,走到预定地点3防御。


image.jpeg

2、处理被狙击的特殊情况:如果玩家从超远距离狙击到AI,如果AI不做出反应,则会被玩家慢慢消灭掉。所以AI必须对狙击情况做出回应——也就是进攻。


image.jpeg

实现这两点之后,咱们的AI虽然精简,但也算是麻雀虽小五脏俱全了,哈哈。抽象地说,我们的AI现在既能利用环境做出掩护动作,又能处理特殊情况防止玩家利用BUG。下图是我最终做完的行为树截图:
image.jpeg

感谢皮皮关的分享,转载于皮皮关的>https://zhuanlan.zhihu.com/p/29598709

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,968评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,682评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,254评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,074评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,964评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,055评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,484评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,170评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,433评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,512评论 2 308
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,296评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,184评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,545评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,150评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,437评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,630评论 2 335

推荐阅读更多精彩内容