UE-AI

学习内容

  • 创建一个可以控制 Pawn 的 AI 实体
  • 创建和使用行为树和黑板
  • 使用 AI 感知为 Pawn 提供视线
  • 创建行为以使 Pawn 漫游并攻击敌人

您可以在此处下载已完成的项目。
请查看环境查询系统 

入门

下载启动项目并解压缩。导航到项目文件夹并打开MuffinWar.uproject

播放开始游戏。在围栏区域内左键单击以生成松饼。

在本教程中,您将创建一个会四处游荡的 AI。当敌人的松饼进入 AI 的视野范围时,AI 会移动到敌人并攻击它。

要创建一个 AI 角色,您需要三件事:

  1. 身体:这是角色的物理表现。在这种情况下,松饼就是身体。
  2. 灵魂:灵魂是控制角色的实体。这可能是玩家或 AI。
  3. 大脑大脑是人工智能做出决定的方式。您可以通过不同的方式创建它,例如 C++ 代码、蓝图或行为树。

既然你已经有了身体,你所需要的只是一个灵魂和大脑。首先,您将创建一个将成为灵魂的 controller

什么是控制器?

 controller是可以拥有Pawn的非物理角色。Possession 允许控制器——你猜对了——控制Pawn。但在这种情况下,“控制”是什么意思?

对于玩家来说,这意味着按下一个按钮并让 Pawn 做一些事情。控制器从玩家接收输入,然后它可以将输入发送到 Pawn。控制器也可以改为处理输入,然后告诉 Pawn 执行操作。

在 AI 的情况下,Pawn 可以从控制器或大脑接收信息(取决于您如何对其进行编程)。

要使用 AI 控制松饼,您需要创建一种特殊类型的控制器,称为AI controller

创建 AI Controller

导航到Characters\Muffin\AI并创建一个新的Blueprint Class。选择AIController作为父类并将其命名为AIC_Muffin

接下来,您需要告诉松饼使用您的新 AI 控制器。导航到Characters\Muffin\Blueprints并打开BP_Muffin

默认情况下,详细信息面板应显示蓝图的默认设置。如果没有,请单击工具栏中的Class Defaults 

转到 Details 面板并找到Pawn部分。将AI Controller Class设置为AIC_Muffin。这将在松饼生成时生成控制器实例。

由于您正在生成松饼,因此您还需要将Auto Possess AI设置为Spawned。这将确保AIC_Muffin在生成时自动拥有BP_Muffin

单击编译,然后关闭BP_Muffin。

现在,您将创建驱动松饼行为的逻辑。为此,您可以使用behavior trees

创建行为树

导航到Characters\Muffin\AI并选择Add New\Artificial Intelligence\Behavior Tree。将其命名为BT_Muffin,然后打开它。

行为树编辑器

行为树编辑器包含两个新面板:

  1. 行为树:此图是您将在其中创建节点以制作行为树的地方
  2. 详细信息:您选择的节点将在此处显示其属性
  3. 黑板:此面板将显示黑板键(稍后会详细介绍)及其值。仅在游戏运行时显示。

与蓝图一样,行为树由节点组成。行为树中有四种类型的节点。前两个是 tasks and composites

什么是任务和组合?

顾名思义,任务是“做”某事的节点。这可能是复杂的事情,例如执行组合。也可以是简单的事情,例如等待。

要执行任务,您需要使用组合。行为树由许多分支(行为)组成。每个分支的根部是一个复合体。不同类型的组合有不同的方式来执行它们的子节点。

例如,您有以下一系列操作:

要执行序列中的每个操作,您将使用Sequence 组合。这是因为序列从左到右执行其子级。这是它的样子:

注意:从组合开始的所有内容都可以称为子树。一般来说,这些是你的行为。在这个例子中,Sequence、Move To Enemy、Rotate Towards Enemy和Attack可以被认为是“攻击敌人”的行为。

如果序列的任何子节点失败,序列将停止执行。

例如,如果 Pawn 无法移动到敌人身边,Move To Enemy将失败。这意味着Rotate Towards Enemy和Attack不会执行。但是,如果 Pawn 成功移动到敌人身边,它们将执行。

稍后,您还将了解Selector组合。现在,您将使用Sequence使 Pawn 移动到随机位置,然后等待。

移动到随机位置

创建一个Sequence并将其连接到Root

接下来,您需要移动 Pawn。创建一个MoveTo并将其连接到Sequence。该节点会将 Pawn 移动到指定的位置或Actor。

然后,创建一个Wait并将其连接到Sequence。确保将其放置在MoveTo的右侧。顺序在这里很重要,因为孩子们会从左到右执行。

注意:您可以通过查看每个节点右上角的数字来检查执行顺序。编号较低的节点优先于编号较高的节点。

恭喜,您刚刚创建了您的第一个行为!它会将 Pawn 移动到指定位置,然后等待五秒钟。

要移动 Pawn,您需要指定一个位置。但是,MoveTo只接受通过黑板提供的值,因此您需要创建一个。

创建黑板

黑板是一种资产,其唯一功能是保存变量(称为键)。你可以把它想象成人工智能的记忆

虽然您不需要使用它们,但黑板提供了一种方便的方式来读取和存储数据。这很方便,因为行为树中的许多节点只接受黑板键。

要创建一个,请返回Content Browser并选择Add New\Artificial Intelligence\Blackboard。将其命名为BB_Muffin,然后打开它。

黑板编辑器

黑板编辑器由两个面板组成:

  1. 黑板:此面板将显示您的按键列表
  2. 黑板详细信息此面板将显示所选键的属性

现在,您需要创建一个保存目标位置的密钥。

创建目标位置键

由于您将位置存储在 3D 空间中,因此您需要将其存储为矢量。单击New Key并选择Vector。将其命名为TargetLocation

接下来,您需要一种方法来生成随机位置并将其存储在黑板上。为此,您可以使用第三种类型的行为树节点:服务

什么是服务?

服务就像您使用它们做某事的任务。但是,您使用服务来执行检查或更新黑板,而不是让 Pawn 执行操作。

服务不是单独的节点。相反,它们附加到任务或组合上。这会产生更有条理的行为树,因为您需要处理的节点更少。以下是使用任务的外观:

以下是使用服务的外观:

现在,是时候创建一个生成随机位置的服务了。

创建服务

返回BT_Muffin并单击New Service

这将创建一个新服务并自动打开它。将其命名为BTService_SetRandomLocation。您需要返回内容浏览器来重命名它。

该服务只需要在 Pawn 想要移动时执行。为此,您需要将其附加到MoveTo

打开BT_Muffin,然后右键单击MoveTo。选择Add Service\BTService Set Random Location

现在,BTService_SetRandomLocation将在MoveTo激活时激活。

接下来,您需要生成一个随机目标位置。

生成随机位置

打开BTService_SetRandomLocation

要知道服务何时激活,请创建一个Event Receive Activation AI节点。这将在服务的父节点(它所连接的节点)激活时执行。

注意:还有另一个称为Event Receive Activation的事件可以做同样的事情。这两个事件的区别在于Event Receive Activation AI还提供了Controlled Pawn。

要生成随机位置,请添加突出显示的节点。确保将Radius设置为500

这将在 Pawn 的500个单位内为您提供一个随机的可导航位置。

注意: GetRandomPointInNavigableRadius使用导航数据(称为NavMesh)来确定一个点是否可导航。在本教程中,我已经为您创建了 NavMesh。您可以通过转到 Viewport 并选择Show\Navigation来可视化它。

如果您想创建自己的 NavMesh,请创建Nav Mesh Bounds Volume。缩放它,使其封装您想要导航的区域。

接下来,您需要将位置存储到黑板上。有两种方法可以指定使用哪个键:

  1. 您可以通过在Make Literal Name节点中使用其名称来指定密钥
  2. 您可以将变量公开给行为树。这将允许您从下拉列表中选择一个键。

您将使用第二种方法。创建Blackboard Key Selector类型的变量。将其命名为BlackboardKey并启用Instance Editable。当您在行为树中选择服务时,这将允许变量出现。

然后,创建突出显示的节点:

概括:

  1. 事件接收激活 AI在其父级(在本例中为MoveTo)激活时执行
  2. GetRandomPointInNavigableRadius返回受控松饼500个单位内的随机可导航位置
  3. Set Blackboard Value as Vector将黑板键(由BlackboardKey提供)的值设置为随机位置

单击编译,然后关闭BTService_SetRandomLocation

接下来,您需要告诉行为树使用您的黑板。

选择黑板

打开BT_Muffin并确保您没有选择任何东西。转到详细信息面板。在Behavior Tree下,将Blackboard Asset设置为BB_Muffin

之后,MoveTo和BTService_SetRandomLocation将自动使用第一个黑板键。在这种情况下,它是TargetLocation

最后,您需要告诉 AI 控制器运行行为树。

运行行为树

打开AIC_Muffin并将Run Behavior Tree连接到Event BeginPlay。将BTAsset设置为BT_Muffin

这将在AIC_Controller生成时运行BT_Muffin

单击编译,然后返回主编辑器。按Play,生成一些松饼,看着它们四处游荡。

这是很多设置,但你到了那里!接下来,您将设置 AI 控制器,以便它可以检测到其视野范围内的敌人。为此,您可以使用AI Perception。

设置 AI 感知

AI Perception 是一个可以添加到 actor 的组件。使用它,您可以为您的 AI 赋予感官(例如视觉和听觉)。

打开AIC_Muffin,然后添加一个AIPerception组件。

接下来,您需要添加一种感觉。由于您想检测另一个松饼何时进入视野,因此您需要添加视觉

选择AIPerception,然后转到详细信息面板。在AI Perception向Senses Config添加一个新元素。

将元素0设置为AI Sight 配置,然后展开它。

视线有三个主要设置:

  1. 视线半径:松饼可以看到的最大距离。将其保留为3000。
  2. 失明半径:如果松饼看到了敌人,这是在松饼看不见之前敌人必须移动的距离。将其保留为3500。
  3. 周边视野半角度数:松饼的视野有多宽。将此设置为45。这将使松饼有90度的视野。

默认情况下,AI 感知仅检测敌人(分配给不同团队的演员)。但是,演员默认没有团队。当演员没有团队时,AI Perception 认为它是中立的。

在撰写本文时,还没有使用蓝图分配团队的方法。相反,您可以告诉 AI Perpcetion 检测中立的演员。为此,请展开Detection by Affiliation并启用Detect Neutrals

单击编译,然后返回主编辑器。按播放并生成一些松饼。按 键显示 AI 调试屏幕。按数字键盘上的4以可视化 AI 感知。当松饼进入视野时,会出现一个绿色球体。

接下来,您将松饼移向敌人。为此,行为树需要了解敌人。您可以通过在黑板上存储对敌人的引用来做到这一点。

创建敌人密钥

打开BB_Muffin,然后添加一个Object类型的键。将其重命名为Enemy

现在,您将无法在MoveTo中使用Enemy。这是因为键是ObjectMoveTo只接受Vector或Actor类型的键。

要解决此问题,请选择Enemy,然后展开Key Type。将Base Class设置为Actor。这将允许行为树将Enemy识别为Actor

关闭BB_Muffin。现在,您需要创建一个行为以向敌人移动。

走向敌人

打开BT_Muffin然后断开SequenceRoot。您可以通过按住 alt 键单击连接它们的线来完成此操作。暂时将漫游子树移到一边。

接下来,创建突出显示的节点并将其Blackboard Key设置为Enemy

这会将 Pawn 移向Enemy。在某些情况下,Pawn 不会完全面向其目标,因此您还可以使用Rotate 来面对 BB entry。

现在,当 AI Perception 检测到另一个松饼时,您需要设置Enemy

设置敌人键

打开AIC_Muffin,然后选择AIPerception组件。添加一个On Perception Updated事件。

每当感知更新时,都会执行此事件。在这种情况下,每当人工智能看到或看不见某物时。此事件还提供了它当前感知的Actor列表。

添加突出显示的节点。确保将Make Literal Name设置为Enemy

这将检查 AI 是否已经有敌人。如果没有,你需要给它一个。为此,请添加突出显示的节点:

概括:

  1. IsValid将检查是否设置了Enemy
  2. 如果未设置,则遍历所有当前感知的演员
  3. Cast To BP_Muffin将检查演员是否是松饼
  4. 如果是松饼,检查它是否死了
  5. 如果IsDead返回false,将松饼设置为新的敌人,然后打破循环

单击编译,然后关闭AIC_Muffin。按播放,然后生成两个松饼,使一个在另一个前面。后面的松饼会自动走向另一个松饼。

接下来,您将创建一个自定义任务以使松饼执行攻击。

创建攻击任务

您可以在内容浏览器而不是行为树编辑器中创建任务。创建一个新的蓝图类并选择BTTask_BlueprintBase作为父级。

将其命名为BTTask_Attack然后打开它。添加一个事件接收执行 AI节点。该节点将在行为树执行BTTask_Attack时执行。

首先,您需要制作松饼攻击。BP_Muffin包含一个IsAttacking变量。设置后,松饼将执行攻击。为此,请添加突出显示的节点:

如果您在当前状态下使用任务,执行将卡在它上面。这是因为行为树不知道任务是否已经完成。要解决此问题,请将Finish Execute添加到链的末尾。

接下来,启用Success。由于您使用的是Sequence,这将允许BTTask_Attack之后的节点执行。

这就是你的图表应该是这样的:

概括:

  1. Event Receive Execute AI将在行为树运行时执行BTTask_Attack
  2. Cast To BP_Muffin将检查Controlled Pawn是否为BP_Muffin类型
  3. 如果是,则设置其IsAttacking变量
  4. Finish Execute会让行为树知道任务已经成功完成

单击编译,然后关闭BTTask_Attack。

现在,您需要将BTTask_Attack添加到行为树中。

向行为树添加攻击

打开BT_Muffin。然后Sequence的末尾添加一个BTTask_Attack

接下来,将Wait添加到Sequence的末尾。将其等待时间设置为2。这将确保松饼不会不断攻击。

返回主编辑器并按Play。像上次一样产生两个松饼。松饼会向敌人移动并旋转。之后,它会攻击并等待两秒钟。如果它看到另一个敌人,它将再次执行整个序列。

在最后一节中,您将把攻击和漫游子树组合在一起。

合并子树

要组合子树,您可以使用Selector组合。与序列一样,它们也从左到右执行。但是,当子成功而不是失败时,选择器将停止。通过使用此行为,您可以确保行为树只执行一个子树。

打开BT_Muffin ,然后在Root节点之后创建一个Selector然后,像这样连接子树:

这种设置一次只允许运行一个子树。以下是每个子树的运行方式:

  • Attack: Selector将首先运行攻击子树。如果所有任务都成功,则Sequence也将成功。Selector将检测到这一点,然后停止执行。这将阻止漫游子树运行。
  • Roam:selector将首先尝试运行攻击子树。如果没有设置Enemy , MoveTo将失败。这也会导致Sequence失败。由于攻击子树失败,Selector将执行其下一个子树,即漫游子树。

返回主编辑器,按Play。产生一些松饼来测试它。

“等一下,松饼为什么不立即攻击另一个?”

在传统的行为树中,每次更新都从根开始执行。这意味着每次更新,它都会先尝试攻击子树,然后再尝试漫游子树。这意味着如果Enemy的值发生变化,行为树可以立即更改子树。

但是,虚幻的行为树的工作方式不同。在 Unreal 中,从最后执行的节点开始执行。由于 AI 感知不会立即感知其他参与者,因此漫游子树开始运行。行为树现在必须等待漫游子树完成,然后才能重新评估攻击子树。

要解决此问题,您可以使用最终类型的节点:装饰器

创建装饰器

像服务一样,装饰器附加到任务或组合上。通常,您使用装饰器来执行检查。如果结果为真,装饰器也将返回真,反之亦然。通过使用它,您可以控制装饰器的父级是否可以执行。

装饰器还具有中止子树的能力。这意味着一旦设置了Enemy,您就可以停止漫游子树。这将允许松饼在检测到敌人后立即攻击敌人。

要使用中止,您可以使用Blackboard装饰器。这些只是检查是否设置了黑板键。打开BT_Muffin,然后右键单击攻击子树的序列。选择Add Decorator\Blackboard。这会将 Blackboard 装饰器附加到序列。

接下来,选择Blackboard装饰器并转到 Details 面板。将Blackboard Key设置为Enemy

这将检查是否设置 Enemy。如果没有设置,装饰器会失败,导致Sequence失败。这将允许漫游子树运行。

为了中止漫游子树,您需要使用Observer Aborts设置。

使用观察者中止

如果选定的黑板键已更改,观察者中止将中止子树。有两种类型的中止:

  1. Self:此设置将允许攻击子树在Enemy无效时自行中止。如果敌人在攻击子树完成之前死亡,就会发生这种情况。
  2. Lower Priority: 此设置将导致较低优先级的树在设置敌人时中止。由于漫游子树在攻击之后,它的优先级较低。

Observer Aborts 设置为Both。这将启用两种中止类型。

现在,如果攻击子树不再有敌人,它可以立即进入漫游状态。此外,一旦检测到敌人,漫游子树可以立即进入攻击模式。

这是完整的行为树:

攻击子树总结:

  1. 如果设置了Enemy Selector将运行攻击子树
  2. 如果设置,Pawn 将向敌人移动并旋转
  3. 之后,它将执行攻击
  4. 最后,Pawn 将等待两秒钟

漫游子树总结:

  1. 如果攻击子树失败,Selector将运行漫游子树在这种情况下,如果没有设置Enemy,它将失败。
  2. BTService_SetRandomLocation将生成一个随机位置
  3. Pawn 将移动到生成的位置
  4. 之后,它将等待五秒钟

关闭BT_Muffin,然后按Play。生成一些松饼,为有史以来最致命的大逃杀做好准备!

猜你喜欢

转载自blog.csdn.net/qq_52825422/article/details/126660747
今日推荐