理解环境查询系统
最后更新于
最后更新于
当人们第一次面对EQS时,可能会感到不知所措,尤其是因为不清楚系统的各个部分如何运作以及为什么这样运作。本节的目标是帮助你理解这个系统,通过熟悉EQS的基础工作流程,这将帮助你在创建查询时实际工作流程。
EQS的一般机制
想象一下,在某个时刻,我们的AI代理处于火力之下,它需要评估不同地方的掩护。一个地方可能很远但保护良好,而另一个地方可能很近但保护不佳。我们应该怎么做?
解决这个问题的方法之一是使用效用函数并及时解方程(我们将在第14章《超越》中详细讨论它们)。实际上,这种方法产生了非常好的效果,并在许多游戏中成功实施。然而,Unreal提供了另一种可能性:EQS。话虽如此,并不强制要求使用EQS而不是效用函数,但作为AI框架的一部分,EQS使得评估此类决策变得容易,因为它是内置系统。
因此,回到需要掩护的代理,行为树将运行一个EQS查询,这将给出代理应该获得掩护的地方的最终结果。现在,环境查询是如何工作的呢?
首先,一个组件(称为生成器,我们稍后会看到)将根据测试中指定的某些标准生成一系列位置(或代理,我们将在本章后面看到)。例如,我们可以在均匀的网格上选择不同的位置,这在事先不知道我们要搜索哪种类型的位置时非常方便(在评估之前)。
然后,有一个可能的地点(或演员)的过滤过程,其中它排除了所有不满足某些标准的地点。在我们的掩护示例中,任何仍然暴露于直接火力的地方都应被丢弃。
剩下的地点会被评估(系统会为其分配一个分数),基于其他标准。再次以我们的掩护示例为例,这可能是代理的距离、它们提供的掩护程度,或者距离敌人的远近。系统通过考虑所有这些因素来分配分数(当然,有些因素会比其他因素更重要;例如,防火保护可能比距离敌人位置更重要)。
最后,得分最高的地点(或演员)将从查询中提供给行为树,行为树将决定如何处理它(例如,快速逃到那个地方寻求掩护)。
环境查询的组成部分
根据我们在前一节中描述的机制,让我们更深入地探讨Unreal中EQS的实际实现。
在高层次上,我们有环境查询、上下文、生成器和测试。
环境查询
顾名思义,环境查询是一种数据结构(类似于行为树),它包含了关于如何执行查询的信息。实际上,它是一个你可以创建并在内容浏览器中找到的资产。
你可以通过右键点击你的内容浏览器,然后选择人工智能 | 环境查询,来创建一个新的环境查询,如下图所示:
这就是它在内容浏览器中的样子:
如果我们双击它来打开它,Unreal会打开一个特定且专用的环境查询编辑器。这个编辑器看起来是这样的:
正如你所看到的,它非常类似于行为树,但你只能将生成器节点附加到根节点(只有一个),这也会使其成为叶子节点。因此,整个“树”将仅仅是带有生成器的根节点。实际上,通过使用类似行为树的编辑器,你可以轻松地设置环境查询。在唯一的生成器节点上,你可以附加一个或多个测试——要么是生成器本身,要么是上下文。这是一个例子:
在下一部分中,我们将理解这意味着什么。
上下文
上下文是一个特定且方便的类的子类,用于检索信息。你可以通过蓝图或C++创建/扩展上下文。
它们被称为上下文的原因是因为它们为生成器或测试提供上下文。有了上下文,生成器(或测试)能够从这一点开始执行所有计算。如果你愿意,可以将上下文视为一个特殊的(且非常复杂的)变量,能够程序化地传递一组有趣的演员和/或位置。
让我们看一个例子,以便我们清楚什么是上下文。在进行测试时,你通常知道查询者(例如需要掩护的代理)的位置(在引擎盖下,即使查询者是默认的上下文)。然而,我们的测试可能需要了解敌人的位置(例如,检查掩护点是否在火力范围内,因为这取决于我们代理的敌人的位置)。上下文可以提供所有这些信息,并且可以以程序化的方式做到这一点:例如,代理可能不知道地图上的每个敌人,所以上下文可能只返回代理当前意识到的敌人,因此它只从这些敌人中寻找掩护。因此,如果代理选择在其位置附近有隐藏的敌人作为掩护,那么对我们的代理来说就倒霉了!
理解上下文并不容易,所以要坚持读完这一章,也许在您对生成器和测试有了更好的理解,以及如何在我们的项目中构建环境查询系统(EQS)之后,再回头重读前面的段落。
生成器
生成器,顾名思义,生成一个初始位置(或演员)的集合(或数组)。这个集合将由测试进行过滤和评估。
生成初始集合的方式完全自由。如果你在评估阶段之前有关于你要寻找的地方的重要信息,那么你可以创建一个自定义生成器(例如,如果代理无法游泳,就不要检查有水的地点,或者如果唯一可用的攻击是近战,就不要考虑飞行敌人)。
像上下文一样,生成器是特定类的子类。你可以在蓝图以及C++中创建生成器。
测试
测试负责过滤和为生成器生成的不同位置(或角色)分配分数(评估)。单个测试可以根据相同的标准进行过滤和评分,也可以只进行其中之一。
在使用过滤的测试情况下,它们试图识别哪些位置(或角色)不符合我们的标准。EQS 经过优化,因此它以特定的顺序执行测试,以尽早检测出不合适的地方。这样做是为了避免分配不会被使用的分数。
一旦所有位置(或角色)都被过滤掉,剩下的将被评估。因此,每个能够分配分数的测试都会在位置(或角色)上执行(执行),并以分数的形式报告评估结果(可以是正数或负数)。
顺便提一下,测试至少需要一个上下文来进行适当的过滤和评估。
让我们看一个简单的测试示例,以理解它们是如何工作的。最常见的测试之一是距离,即这个位置(我们正在评估的生成物)离上下文有多远?上下文可以是查询者,或者是它攻击的敌人,或其他任何东西。因此,我们可以(例如)过滤掉超出或低于某个距离阈值的地方(例如,如果它们离玩家太远,我们可能不想要完美的掩护地点)。同样的距离测试可以根据距离分配分数,如果上下文很远(或很近),分数可以是正数(或负数)。
此外,测试有一个评分因子,代表测试的权重:测试的重要性,以及在计算当前评估的位置(或角色)的最终分数时,该测试需要产生的影响。实际上,你将在生成器生成的位置上进行许多不同的测试。评分因子使你能够轻松地对它们进行加权,以确定哪个测试对位置(或角色)的最终分数影响更大。
每个测试在详细信息面板中的选项具有以下结构:
Test:在这里,你可以选择测试的目的是过滤和评分,还是其中的一部分,并添加描述(这对测试没有影响,但你可以将其视为回忆测试内容的注释)。此外,可能还有其他选项,如你可以与导航系统一起使用的投影数据(适用于依赖导航系统的测试)。 Specific Test: 这是存放测试具体选项的地方。每个测试的具体选项可能会有所不同。
Specific Test:这是存放测试具体选项的地方。每个测试的具体选项可能会有所不同。
Filter:在这里,你可以选择过滤器的表现方式。这会根据测试的不同而有所不同,但通常你可以选择一个过滤器类型,这可以是一个范围(或最小值或最大值)在测试将浮点数作为返回值的情况下;否则,在条件测试的情况下,它可以是布尔值。如果测试目的设置为仅评分,这个标签不会出现。
Score:在这里,你可以选择评分的表现方式。这会根据测试的不同而有所不同。对于测试的浮点返回类型,你可以选择一个评分方程,以及归一化。此外,还有评分因子,这是该测试与其他测试相比的权重。对于布尔返回值,只有评分因子。如果测试目的设置为仅过滤,这个标签不会出现。
Preview:这给你提供了过滤和评分函数的外观预览。
如你所见,这些选项非常容易理解,如果你通过EQS进行练习,你会更好地理解它们。
组件的视觉表示
这些组件在开始时可能不太直观,但一旦你习惯了EQS,你会意识到它们的意义,以及为什么系统是这样设计的。
总结各个组件及其重要性,并为您提供一个视觉表示,以下是一个您可以参考的图表:
在行为树中运行环境查询
最后,要完全理解环境查询如何工作的最后一步是看它如何在行为树中运行。幸运的是,我们有一个名为“run EQS”的节点,这是一个内置的行为树任务。在一个假设的行为树编辑器中,它看起来如下所示:
可以在详细信息面板中找到的可能设置如下:
如你所见,许多内容已经被弃用(所以只需忽略它们),但我已经突出了最重要的部分。以下是它们的解释:
黑板键:这是一个引用黑板变量的黑板键选择器,EQS 的结果将存储在其中。
查询模板:这是对我们想要运行的 EQS 的具体引用。否则,我们可以停用此选项以激活 EQSQuery 黑板键。
查询配置:这些是查询的可选参数(不幸的是,我们在这本书中不会详细讨论它们)。
EQSQuery 黑板键:这是一个引用包含 EQS 的黑板变量的黑板键选择器。如果激活,将执行黑板变量中包含的 EQSQuery,而不是查询模板中的 EQSQuery。
运行模式:这显示了我们将要检索的查询结果。可能的选项如下:
单个最佳项目:检索得分最高的点(或演员)。
来自最佳 5% 的单个随机项目:从得分最高的 5% 的位置(或演员)中检索一个随机点。
来自最佳 25% 的单个随机项目:从得分最高的 25% 的位置(或演员)中检索一个随机点。
所有匹配项:检索所有匹配查询的位置(或演员)(它们没有被过滤掉)。
这就构成了如何运行 EQS 并检索其结果,以便在行为树中使用。
不仅是位置,还有Actors! 我强调了很多次“...评估一个位置(或Actor)...”。
事实上,EQS 最酷的功能之一是不仅可以评估位置,还可以评估actors!
再次,你可以将EQS(环境查询系统)作为一种决策过程。想象一下,你需要选择第一个攻击的敌人。你可能需要考虑各种参数,例如该敌人的剩余生命值、它的实力,以及它在近期内被视为威胁的程度。
通过仔细设置EQS,你可以根据哪个敌人最方便攻击,为每个敌人分配一个分数。当然,在这种情况下,你可能需要投入一些工作来创建适当的生成器,以及上下文和适当的测试,但从长远来看,当代理需要做出这类决策时,EQS是一个非常不错的选择。