• 参考
  • ECA
  • 行为树

行为树

概览

行为树是实现游戏AI的一种方式。游戏中的AI让单位通过模拟真实玩家的行动而拥有“智能”行为。例如PVE的敌人,BOSS的战斗模式,玩家召唤物等。作为玩法的重要组成部分,增强玩家的参与感。行为树即是用树状结构分支使AI能根据条件执行不同行为(如走、跑、跳、攻击)。

初始化

使用行为树之前,先初始化。们可以建立全局变量储存经常使用的玩家角色和需要被控制的敌方单位。

建立全局变量“unitPlayer”储存玩家单位。建立另一个全局变量单位组以储存所有敌方单位。

为了更沉浸的游玩体验,你可以设置“镜头 - 跟随单位”以让玩家的视角能始终跟随在自己的英雄上。

可以通过动作:“玩家-选择单位”,让玩家选中自己的主控单位。

S3-1

循环检查所有地方单位并对他们应用行为树

每个单位都需要具有自己的智能行为,并且不同类型的敌人面对相同的情况会采取不同的措施,所以我们需要先遍历全局中的敌方单位组,并根据其单位类型进行分敛。

当游戏开始经过‘1秒’时,也即是游戏初始化结束,游戏中的AI就应当开始行动了,我们所有的敌人已经事先储存在全局的单位组中,所以只需要对这个单位组进行循环的遍历即可。

也即是说,存在两个循环,每‘N’固定事件间隔遍历一次单位组,每次遍历单位组时对每个单位都应用其对应的行为树判断一次。

在本次的示例中,我们存在两种不同的AI,它们分别是‘近卫’和‘治疗者’,根据单位的单位类型即可分辨出应该对其运行哪个行为树。

S3-2

在过滤了单位类型以后,通过条件判断语句将单位输送给不同的自定义事件,并设置好参数,也即是将需要执行行为树的那个单位作为参数传递。

在Y3编辑器中,你可以在自定义事件中先新建一个事件,之后就可以使用动作发出,并在其他触发器的事件出选择接收。

在新建事件时,根据需要添加需要传递的参数,参数必须是变量,但不支持数组。

比如行为树是针对某单位执行,那么就需要将单位作为参数传递出去。

之后在执行行为树的触发器内,将事件设置为自定义事件,并接收参数,即完成了对单位的分敛和分发。

s3-3

s3-4

而独立的‘守卫’行为树,或者‘治疗者’行为树则只对传输过来的这个单位执行效果,判断这个单位的状态和周围的状态,并根据状态决定出其接下来将要执行的动作,截止到此处,您已经完成了该功能的结构框架。

‘守卫AI’的实现

守卫通过自定义事件:"AI_Guard"来接收需要执行效果的单位。

新建一个单位类型局部变量,命名为unit,用它来储存这个从上一个触发器传递过来的单位。

守卫会先判断是否有敌人能够威胁到治疗者,如果有,守卫会优先保护治疗者。

新建一个实数类型局部变量,命名为distance,用于储存敌人和治疗者之间的距离。

通过判断这个数据是否小于300来判断治疗者是否安全。

s3-5

如果距离小于300,则给单位unit向储存在全局变量中的玩家角色unitPlayer一个攻击指令。

如果治疗者是安全的,那么继续判定守卫单位自身的HP是否是安全的,检测unit的HP是否低于其MaxHP的50%。

如果守卫单位本身的HP不安全,则给单位unit向全局变量中的治疗者unitHealer一个移动指令。

如果守卫单位本身是安全的,则判断AI警戒区域(在本示例中为一个圆形区域)内是否有敌人。

如果有敌人,则攻击这个敌人。

如果没有,守卫则会在警戒区域内随机移动巡逻。

s3-6

‘治疗者AI’的实现

治疗者通过自定义事件:“AI_Healer”来接收需要执行效果的单位。

与守卫AI类似的,先对需要执行的单位以局部变量进行储存。

先判断治疗者自己的HP是否等于其MaxHP,它会优先保障自身的安全。

在治疗者本身是满HP状态下,它会治疗自己的其他友军。

在这里,我们需要新建一个‘获取当前HP最低的友军’函数来查找当前最需要治疗的友军。

S3-7

在函数一开始,我们需要先新建一些局部变量,一个实数类型,另一个是单位类型。

这两个变量分别用于表示HP的百分比以及我们想要的那个单位,单位初始为‘空’,表示没有单位需要治疗。

通过遍历所有单位的单位组来获取HP最低的单位。

我们比较每一个单位的当前HP百分比,并和我们的实数变量作比较。

如果如果它比储存的实数更小,说明它比之前储存的单位更需要治疗,我们把新的百分比和单位都写入到变量中。

当遍历完全以后,我们就获取到了单位组中HP百分比最低的那一个单位。

把储存有这个单位的变量作为返回值,我们就完成了一个可以筛选出最需要治疗单位的函数。

S3-8

在创建好函数以后,我们就可以使用这个函数获取我们想要的单位,当然别忘了为它新建一个单位类型的局部变量用来储存它。

s3-9

接下来,我们确定获取到的这个单位是否是一个空单位。

如果是,说明当前没有单位需要治疗,那么它将充当一个‘法师’的身份。

判断自己身边是否有敌人,如果有,就使用飞弹攻击它。

如果周围不存在敌人,那么治疗师会保持在警戒区域的中心不动,以方便巡逻的守卫保护自己。

s3-10

如果我们获取到的返回值单位并不是一个空单位,说明当前有需要治疗的单位,治疗师就会停止当前的动作,并为这个单位治疗。

为了让这种动作更具真实感,我们可以播放对应的动画动作,并为治疗效果添加一个特效。

因为在这里,我们并非使用‘技能’来实现治疗,所以为了让治疗者不会边攻击边治疗,我们需要为其发布一个停止命令。

S3-11