AI行为树

如何完成行为树的实现的呢,要找清楚黑板,行为树,AI_Controller的关系,黑板实际上就是行为树的数据库。

1.       先进行整体架构,创建Character,AIController,行为树,黑板,将其关系理顺,首先将控制器与角色链接在一起,让控制器去控制角色,其次在控制器中实现行为树,Run BehaviorTree,再者就是将黑板绑定到行为树上去使用,在行为树中Detail面板中的BlackBoard绑定上刚创建的黑板,这样就将四者联系在一起了。

2.       架构行为树,Root节点下只能链接一个Composites节点,架构过程中暂时全都用Selector,之后有需要进行更改,设想一下还是有四个状态,Patrol,Chase,Attack,Back,接着在下面分别添加四个Selector,每个下面添加一个Task.(写逻辑)

3.       如何实现四种状态下的切换呢,还是要用到枚举,写入四种不同的状态,状态有了,如何切换呢,那么想到要用到枚举种不同的状态,黑板是行为属的数据库,想用枚举这个数据就要将枚举添加到数据库中,四种状态的Selector分别都添加一个黑板但是每个黑板所呈现的枚举状态不同,这样就可以实现,改变黑板上的State来实行切换状态。

这是添加到Selector上的黑板可编辑的东西,FlowControl值得是这条分支的流程,如果其中的Result或者Value改变那么就会出现改变Flow,(Observer aborts(改变什么))。

下边的Blackboard呢,Key Query是判定条件,(等于,大于,小于等等)BlackboardKey是黑板中的关键值,需要什么选什么,KeyValue是关键值得大小或者选项等等。通过改变KeyValue来对四纵不同的状态进行定义。

4.       基本整体架构就是这样,下面接着先写Patrol,首先要完成的自己巡逻状态,打开Task,覆写一个Tick事件作为驱动,首先用的节点就是SimpleMoveToLocation,这里需要输入两个值,Controller和Location,Comtroller的输入有两种方法,第一中就是将Controller写进黑板,初始化赋值之后使用。第二种较为简便,其实Tick事件上的Owner Actor就是一个Controller,只需要将其Castto为需要的AI_CON就可以了,那么Location就要需要黑板传入了,这里只介绍一次,黑板上的值如何初始化和使用,之后一笔带过,但这也是行为树中比较重要的地方。首先在黑板上创建一个Vector的变量,命名为HomeLocation,然后在Task中调用,先创建一个BlackBoard类型的变量,从中引出一个GetBlackBoardValueAsVector。但是此时并不能保证所连的Vector就是HomeLocation,将黑板变量眼睛打开,编译,点击行为树中的Task就会发现多了一个Default,而变量就是黑板变量,在黑板变量中选择Homelocation就OK了,这样就保证了引出的Vector就是Homelocation。还需要一个让其四处移动的一个节点,GetRandomPointinNavigableRadius(在AI->Navigable中可以找到),设置好后链接到Goal上,这时还是不可以移动,那是因为HomeLocation还是个空值,没有对他进行赋值,这时候就要在Controller中进行赋值了。

5.       在赋值的时候有一个细节不可以忘记SetValueasVector节点上的KeyName是说要付给值得名字,这时候要创建一个Name变量,但是切记创建完变量后编译后一定要将DefaultValue改成要改变的名字。

6.       120帧是1秒。

7.       将动画设置好,那么自动巡逻就写成了。

8.       但是不意味着Patrol这个状态就结束了,这个状态下还是要写发现Player并跳转到Chase状态,因为这里跳转状态会经常用到,那么我就直接将将其写作一个Task,ChangeStateTo.

9.       就用上述的方法,创建一个黑板变量引出SetBlackBoardValueasEnum,可以直接改变Value的值来控制切换的是哪个状态,但是这样很不方便,为了直观,可以再创建一个Enum变量并打开眼睛,使其在Task中可以改变。这样改变状态是完成了,可是如何跳转下去呢,在Task中完成跳转的节点是FinishExecute,如果Success就会返回到根节点,如果Success没有选中,那么回从左向右跳到下一个子节点。但是这里我们改变状态当然是希望跳转回根节点,重新进入分支。

10.   这时发现还是缺少一个事件,就是FindTarget,创建并打开,因为Find的话就要每帧都去检测,所以复写一个Tick事件,还是用之前的方法进行检测,PawnSensing,在Controller中添加事件OnSeePwan,附一个值传给黑板,在Task中判断这个值是否有效,有效则进行跳转。不要忘记在最后写上FinishExecute,但是这个要是Success不选中的,因为想让其条状到ChangeTask上。

11.   这是发现问题了,巡逻Task是不断在改变位置的,不能进行跳转,换句话说是常态,不能进行判断跳转,并且跟Find是并列关系,所以这里可以考虑用SimpleParallel,平行关系,但是主支可以操控跳转,副支跟随着主支跳转,自己不能控制。正好适用我的这个情况。这样Patrol就算写完了,接下来写Chase.(这里简述一下SimpleParallel,(插播概念以及细节)它与Selector,Sequence统称为Composites节点,Composites节点定义一个分支的根以及该分支如何执行的规则,规则可以有Decoratars(装饰者)节点决定,此外也可以将Services节点附着在上面,不过Services要在其子节点执行之后才开始生效。行为树的节点也就分为四种:Composites,Decoratars,Service,Task。Composities节点中需要注意的是执行顺序,还有要注意的是SimpleParallel中的FinishMode,其中两种方式分别是Immediate(主任务完成后,整个背景树执行终止)Delayed(主任务完成后,背景树继续执行),在Decorators中暂时先更新一个BlackBooard,在Detail面板中FlowControl下Notify Observer(节点检测)下有两个选项,OnresultChange(条件发生变换时继续评估)OnValueChange(观测的黑板键发生变化时再次评估,存在疑问),下面的ObserverAborts(检测中止abort流产中止,其中LowerPriority是指终止此节点右边的节点),剩下的都提过,)

12.   先下ChaseTask,追踪的话还是用节点,SimpleMoveToActor。事件写完之后就要考虑可能出现的情况了,距离小于攻击距离+50就切换至Attack状态,距离大于追踪距离就切换至Back状态。这里如果用之前的Patrol状态的方法也可以,但这里使用一个新的方法,Service.

13.   Interval间隔时间,休息时间,deviation偏差值,这是Service的俩个可编辑的值,主要意思是Service有一套自己的时间轴,可以编辑的间隔时间和偏差值。只有进入此支线时Service才起作用,在其中写什么呢,主要写当距离小于攻击距离+50就切换至Attack状态,距离大于追踪距离就切换至Back状态。这里就不需要用finish来进行跳转了,那么如何完成跳转呢,上面说过,在黑板上有控制FlowControl,这里就用到了,将这个Selecter上的黑板上的FlowControl修改,这里是改变了StateEnum所以将NotifyObserve改为OnResultChange,Observe aborts改为Both,就会出现当Service中将State中的值改变了,那么久会直接回到根节点。因为Service的时间轴是独立的,所以会有误差。

时间: 2024-08-10 00:07:43

AI行为树的相关文章

AI行为树的工作原理

最近在项目中应用到了行为树,在网上看了不少关于行为树的文章,其中有一篇文章我觉得写得非常到位,它的原文是英文.在这篇文章里我会它的大致意思给翻译出来(注:由于原文有不少啰嗦的地方,所以没有逐句的翻译),以它的行为结构为标准,并会在译文中穿插一些自己的理解来谈谈我眼中的行为树. 原文链接 一.介绍 尽管网上已经有大量关于行为树的教程,但是在开发游戏中的 AI 时还是遇到了不少关于行为树的问题.很多教程不关注于代码的实现,而是给出一些非常笼统的节点图,就像这样: 这些节点看起来非常的抽象,这对于我了

AI行为树关键字分析

Decotator(装饰)既然作为条件判定分为了三种判定类型, 第一:控制输入的类型,比如BlackBoard 第二:控制输出的类型,比如Force Success 第三:控制执行方式,比如Loop 系统中自定义了很多常用的Decotator,IsAtLocation(判断是不是在某个坐标) ForceSuccess(强制输出成功) CampareBBEntris(比较两个黑板Key) Loop(循环,可以设置次数) ConditionLoop(达成条件在进行循环)(条件通过KeyQuery设定

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

参考链接: https://blog.csdn.net/linxinfa/article/details/72937709 https://blog.csdn.net/wanghaodiablo/article/details/52587364 https://blog.csdn.net/q414620221/article/details/78596732 0.节点 一般情况下,只需要扩展Conditional和Action这两种节点即可,Decorator和Composite节点只需要使用内

B-树、B+树、红黑树

B-树 B-tree树即B树,B即Balanced,平衡的意思,B-树又称为多路平衡查找树.因为B树的原英文名称为B-tree,而国内很多人喜欢把B-tree译作B-树,其实,这是个非常不好的直译,很容易让人产生误解.如人们可能会以为B-树是一种树,而B树又是另一种树.而事实上是,B-tree就是指的B树. 一.定义 B-树是一种多路搜索树(并不一定是二叉的) 1970年,R.Bayer和E.mccreight提出了一种适用于外查找的树,它是一种平衡的多叉树,称为B树(或B-树.B_树). 一棵

UE4简单AI

非常有幸能加入到虚幻四教育的队伍中,一直没更博也是这个原因,最近在翻译官方wiki 上的AI部分视频,有童鞋建议把翻译的文字稿也发上来,所有就有了这篇文章了. 首先做个小小的声明把,由于俺之前也没接触过AI ,所以有一些专业的词汇可能翻译存在各种问题,如果你发现的话,还是希望能够提出来哦,我们一起进步. 记住配合视频食用更佳哦~ 视频连接:http://www.unrealedu.org/course/15/learn#lesson/79 此外,我也在翻译官方那本C++的教程,已经读完,想着还是

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

B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树:⑴树中每个结点至多有m 棵子树:⑵若根结点不是叶子结点,则至少有两棵子树: ⑶除根结点之外的所有非终端结点至少有[m/2] 棵子树:⑷所有的非终端结点中包含以下信息数据: (n,A0,K1,A1,K2,-,Kn,An)其中:Ki(i=1,2,-,n)为关键码,且Ki<Ki+1,  Ai 为指向子树根结点的指针(i=0,1,-,n),且指针Ai-1 所指

转:基于B-树和B+树的使用:数据搜索和数据库索引的详细介绍

原文地址:http://www.jb51.net/article/36184.htm B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树:⑴树中每个结点至多有m 棵子树:⑵若根结点不是叶子结点,则至少有两棵子树: ⑶除根结点之外的所有非终端结点至少有[m/2] 棵子树:⑷所有的非终端结点中包含以下信息数据: (n,A0,K1,A1,K2,-,Kn,An)其中:Ki(i=1,2,-,n)为关键码,且Ki<

B-树&amp;&amp;B+树&amp;&amp;数据库索引(转)

文章来源 http://blog.csdn.net/hguisu/article/details/7786014 http://blog.sina.com.cn/s/blog_4e0c21cc01010gjo.html 一.B-树 它就是B树,不存在所谓的B减树,中间的横杠只是隔离符,即平衡多路搜索树,此处B是Balance的意思. B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树:⑴树中每个结点至多有m 棵子树:⑵若根结点不

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

B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树: ⑴树中每个结点至多有m 棵子树: ⑵若根结点不是叶子结点,则至少有两棵子树: ⑶除根结点之外的所有非终端结点至少有[m/2] 棵子树: ⑷所有的非终端结点中包含以下信息数据: (n,A0,K1,A1,K2,-,Kn,An) 其中:Ki(i=1,2,-,n)为关键码,且Ki<Ki+1,  Ai 为指向子树根结点的指针(i=0,1,-,n),且指针Ai-