文章目录
行为树的基本概念
1 行为树基本上分为Composites和Tasks,也就是节点和节点里的任务
2 行为树的执行顺序是从左到右
创建一个最简单的行为树
创建树
右键“人工智能/行为树”
打开行为树,从根节点下边的区域里往外拖,创建一个序列节点
从Sequence的区域里往外拖,选择Tasks,我们创建一个播放动画
设置好要播放的动画
再Sequence里拖一个Task出来,这次选择等待,并设置好等待的时间
使用树
打开角色控制类,RobotController,之前我们使用的代码控制寻路逻辑,现在要改为使用上边创建的行为树
使用运行行为树节点,并选择行为树
运行,就可以看到机器人跳一下,再等两秒,然后循环
黑板
黑板用来给行为树提供数据
创建一个黑板
右键“人工智能/黑板”
为行为树指定黑板
打开行为树,不要选择任何节点,右侧BehaviorTree里指定黑板
指定黑板后,可以在右上角直接切换行为树和黑板
新建一个变量
我们新建一个追踪对象
打开黑板,左上角选择新建/Object。Object就是所有类型的基类,我们需要在右侧面板进一步指定我们需要的类型,可以是我们自己定义的蓝图类
修改如下属性,注意他的基类需要是一个Actor才能被作为追踪的对象
角色本身的Controller脚本(不是蓝图类)里使用黑板并设置属性的值
使用“使用黑板”节点显式的指定要使用的的黑板,然后将黑板里的Enemy属性的值设置为玩家
注意点1:黑板字段节点可以直接使用,无需生命
注意点2:KeyName是一个引用,可以从节点拖出来,然后选择提升为变量,或者使用"创建文字命名节点 Make Literal Name"
其角色类里获取黑板并设置属性的值
不提升变量也可以用这个节点创建KeyName
在Task里设置黑板的值
重点是key的设置方式比较特殊
行为树使用黑板里定义的属性
最后修改一下行为树,添加一个MoveTo的Task
追踪半径设置为3米,黑板的键设置为Enemy
此时运行,可以看到敌人在追击玩家
自定义Task
行为树左上方可以自定义任务
任务也是一个蓝图类,所以我们需要新建起一个名字,这里我们新建一个名字为AlwaysTrue的Task,放在行为树同级目录
编辑Task的蓝图,在事件图表里追加如下
1 节点开始执行事件
2 打印一下名字,这里展示了事件传入的参数OwnerActor的actor,其类型是机器人的AIController
3 延迟一下在执行,我们在行为树里设置的等待时间是2秒,如果不给个延迟,会导致打印还没有消失就再打印一条,这个节点不是必须的
4 必须要有一个结果节点,这里我们固定返回值为true
Sequence和Selector
Sequence:从第一个为false的子节起,后边的都不再执行,自己也返回false
Selector:从第一个为true的子节点起,后边的都不再执行,自己返回true
Decorator装饰器
装饰器使用来附加到Sequence/Selector等节点上的判断条件,用来判断是否可以进入这个节点
自定义一个装饰器
行为树左上角新建一个装饰器,命名为D_AlwasysTrue,装饰器也是一个蓝图类
和Task不同,装饰器要重写的不是事件,而是方法
我们重载“执行条件检查"方法,不要"重载执行条件检查AI"方法,这个方法经实测会覆盖"执行条件检查"方法
他的返回值设置为永远为true
使用装饰器
在行为树里,选择一个节点,右键/付加装饰器,即可付加装饰器,只有装饰器返回为true时,才会执行节点里的内容
黑板装饰器
一个常用的内置装饰器,用来检查黑板上的数据是否符合预期
观察器中止:self,如果不满足条件,立刻返回false none,如果不满足条件,等待后续节点执行完再返回false
黑板:如何检查黑板上的数据
Service
1 Service被附加在混合节点(Sequence,Selector)上,当处于这个节点状态时,就会执行Service的方法,来用和行为树的叶子并行执行
2 Service会每隔一定时间自动调用
3 无论混合节点的结果是true还是false,Service一定会被调用
4 使用案例,走路用行为树节点,一边走路一边开枪用Service
自定义一个Service
行为树左上方,新建一个Service
在事件图表里,添加”事件接收Tick Event Receive Tick“节点,后续跟逻辑
使用Service
右键一个混合节点,选择添加服务,选择要添加的服务
选择服务,右侧有他的属性,定义了多久执行一次以及时间偏移
一个完整的行为树示例
要实现的逻辑
1 寻找敌人
2 如果没找到,等待2秒,跳转到1
3 如果找到了,走向敌人
4 走向敌人的过程中,如果看见敌人,则射击
5 如果敌人没有了,则跳转到1
实现
1号序列进入行为树,2开始寻找敌人,将寻找的结果放到黑板的enemy变量里
然后进入3,3进入5号装饰器,判断黑板的Enemy变量的是不是空
如果是空进入8号等待节点,2秒后返回2号节点,如果不是空,开始执行4号序列,寻路的同时向敌人射击
ShootEnemy Service的实现
ShootEnemy是在RobotShooter蓝图里新定义的方法