
本节介绍游戏设计中的AI。
在游戏中你经常能见到很聪明的敌人,它可以攻击,可以闪避,在血量低时会逃跑。这些敌人的行为的背后是由一个AI统一管理的。
如果把敌人的行为逻辑都写在一个脚本里,显然有些太过臃肿。因此我们会使用一种叫行为树的编程思想来编写敌人AI。
如果你从来没听说过行为树,那么推荐先去学习一下行为树的基本逻辑。如果没学过也没关系,我会一次性把重要的内容讲清楚。
行为树是一个树状结构,在每一帧,从根部出发,默认按照从左到右,从上到到下的顺序运行。

比如上图,就是先运行左边第一个组合,然后运行下面的叶子节点,随后是右边的第一个组合,然后是下面的叶子节点或第二个组合。依次类推
组合节点就是你用来编写行为树逻辑的核心节点,用于改变行进的分支
组合节点常用的有两个:序列器和选择器
序列器的作用是:子节点失败就停止运行并返回失败,子节点成功就运行下一个子节点,如果全部成功就返回成功
也就是说,序列器一旦碰到失败的子节点就会返回失败,只有全部子节点成功才会返回成功
选择器的作用是:子节点成功就停止运行并返回成功,子节点失败就运行下一个子节点,如果全部失败就返回失败
也就是说,选择器只要有成功的子节点就会返回成功,只有全部失败才会返回失败
叶子节点就是行为树的最末端。叶子节点通常会有条件节点和行动节点两种,条件节点是满足条件就会返回成功,不满足就返回失败。行动节点是执行角色的行动,比如攻击,移动等。
仅依靠这些节点,我们就已经能写出相当复杂的AI了。
那么在Godot中,我们可以自己编写行为树组件,也可以直接使用社区的免费插件,比如Beehave插件。在Github上下载好Beehave插件的压缩包,然后解压出来,把addons和script_template文件夹直接丢到游戏资源根目录下:

然后在项目设置-插件内点击启用:

这样我们的游戏引擎就有了Beehave插件的节点了:

关于Beehave插件的用法,你可以直接到官网学习,站内也有不错的搬运教程。
在你的敌人的根节点下添加BeehaveTree节点,然后搭建一个行为树:

以上图为例,这就是一个简易的待机-警惕-追逐的行为树。
敌人在玩家靠近后会警惕,在过近时会向玩家冲去:

这样我们就完成了一个简易敌人AI
(行为树的代码逻辑和以往我们接触的有很大出入,如果你不知道具体代码怎么写,请看下面的实例)
条件叶子节点:
@tool
extends ConditionLeaf
func tick(actor: Node, blackboard: Blackboard) -> int:
var mushroom:MushRoom = actor
if mushroom.state == MushRoom.EnemyState.CHASE:
return SUCCESS
else:
return FAILURE
动作叶子节点:
@tool
extends ActionLeaf
func tick(actor: Node, blackboard: Blackboard) -> int:
var mushroom:MushRoom = actor
if mushroom.position.x > mushroom.player.position.x:
mushroom.direction = -1.0
mushroom.animation.scale.x = -1.0
else:
mushroom.direction = 1.0
mushroom.animation.scale.x = 1.0
mushroom.velocity.x = mushroom.speed * mushroom.direction
mushroom.animation.play("Walk")
return SUCCESS