揭秘神秘海域2的敌人AI The Secrets Of Enemy AI In Uncharted 2

2018/06/07 Game Design

在最新一期的Uncharted 2战斗设计系列中,Naughty Dog战斗设计师Benson Russell深入研究了该工作室为其战斗AI设计的技术,以及这些技术是如何从该系列的原始游戏中演变而来的。第一部分讨论了团队如何从最初的Uncharted演变出战斗设计第二部分看看战斗触发设计。

本文的原文地址在 https://www.gamasutra.com/view/feature/134566/the_secrets_of_enemy_ai_in_.php?page=1 是系列的第一部分

螺母和螺丝

我想分享我们AI系统的一些基本技术细节,以深入了解我们如何解决当我们作为开发人员时都会面临的一些常见AI问题。大多数游戏都有某种形式的AI,不管游戏的类型如何,这是相当普遍的要求而且必须得到满足。所以我认为你应该能够将这里的很多方面与你正在使用的系统联系起来,并且可能启发你可以去尝试一两个新事物。 我们的AI包含一系列非常模块化的系统,可处理我们所需要的不同方面。从高级角度来看:

  • 有设计师界面组件可以让我们为玩法定义角色和行为。
  • 有美学元件可以处理它们的外观和动画。
  • 有决策组件可以选择去哪里,如何到达那里,以及沿途和前进的方向。

我们尽量保持系统尽可能模块化,因为它可以让我们快速实验并用新想法和游戏机制原型进行原型设计。当系统需要交叉沟通时,它可能会导致一些问题,但好处远大于坏处。 就本文而言,我想坚持从设计师的角度来处理我们最主要的问题,所以这就是我最关注的问题。

你是大脑…是中枢神经系统…

我们定义AI类型的方法是为所有不同的AI系统创建一组默认数据。这是非常开放的,让我们有能力创建我们想要的任何类型的行为,而无需通过编程支持将它们硬编码到引擎中(尽管我们可以在特殊情况下使用该路线)。我们使用我们的自定义脚本语言作为设置这些参数的主要方法,以及在游戏过程中与它们进行交互。让我们仔细看看我们如何设置AI:

原型

因此,在定义这些设置的最高级别中,我们有所谓的原型。这形成了在游戏中产生这种特殊类型的AI时使用的默认数据集的起点。我们创建原型,然后将其分配给放置在关卡中的AI游戏对象。例如,这里是定义神秘海域2中轻型手枪士兵的原型(使用Defender手枪的浅灰色制服的家伙):

(define-ai-archetype light-pistol
:skills (ai-archetype-skill-mask
script
hunting
cover
open-combat
alert
patrol
idle
turret
cap
grenade-avoidance
dodge
startle
player-melee-new
)
:health 100
:character-class ‘light
:damage-receiver-class ‘light-class
:weapon-skill-id (id ‘pistol-basic-light)
:targeting-params-id (id ‘default)
)

这是一个简单的结构,其中包含了了解AI的能力所需的所有数据。除了这个例子显示的内容,还有更多的选项可以包含在这些内容中,但是这些数据是让AI执行的“肉”和“土豆”。

得到技能

您可以看到其中一项数据(可能是最重要的一项)是技能列表(skills)。就他们的能力而言,这是我们的AI的核心。它的设计是模块化的,因此可以简单地添加和删除技能。以下是本示例中所用技能的一些说明:

  • 脚本:这允许AI通过我们的脚本语言而被接管。它基本上关闭了他们的大脑,并允许他们响应脚本命令。如果我们需要AI来播放特定的动画,或者我们希望命令它们移动到特定的点,我们就会使用它。这是需要的,因为如果没有它,他们仍然会思考并试图自己采取行动,因此他们最终会反对执行向他们发出的命令。

  • 掩护:这让他们了解掩护以及如何使用掩护(稍后我会详细介绍掩护系统)。对于我们不想让他们有掩护的角色,我们可以简单地删除这个技能。

  • 开展战斗:这告诉AI如何在掩护外开展战斗。

  • 炮塔:这让AI可以在游戏玩法上和技术上(即播放什么动画)使用安装的炮塔。

  • 空闲:这让他们了解空闲行为(即当该地区没有敌人时)。

  • 巡逻:这使得AI可以了解如何使用我们在自定义编辑器Charter中布置的巡逻路线。

  • CAP:这是Cinematic Action Pack的缩写。 行动包(AP)通常是我们如何让AI针对特定情况执行某些动画(例如跳过墙壁或跳墙)。 CAP是一种让AI执行所需表现(如抽烟)的方式,但他们的大脑仍然有它们的大脑,因此它们可以响应刺激。 CAP将定义所有需要的动画,以及过渡动画以使AI进出不同的状态。

除了我在这里展示的技能之外,还有更多的技能,每个技能都被设计为模块化的组件来告诉AI如何针对各种游戏玩法作出反应。 这使得向AI添加功能非常容易,因为程序员只需编写插入列表的新技能即可。 我们也可以选择通过我们的脚本语言在游戏过程中动态添加和移除技能。

生命值(Health)

生命值参数应该是自我解释的。我们特别从中神秘海域1使用的浮点值切换到神秘海域2使用的整数值。原因是我们在浮点系统中出现了一些不可预知的行为(即检查值为1.0,但是它的值为0.999999)。

对玩家来说,最终的结果是有时敌人需要额外的子弹才能击倒。同样为了保持简单,我们尝试给所有对象提供100 Health(AI和玩家)的基础。当我们想要一个真正强大的敌人(比如重型连锁枪手)时,有一些例外情况,但是大多数情况下我们想要一致性,所以很容易平衡(在这一点上)。

AI和类

角色类决定了动画集中设置的角色的外观。这些类是程序员和动画师之间定义的。 对于神秘海域2我们有轻型,中型,重型,装甲,盾牌,村民和SLA等多个类(一个有趣的额外说明,SLA代表香格里拉军团,它们是和德雷克最后在生命之树战斗的)。

伤害

伤害接受者类是我们根据敌人从不同的玩家武器中受到多少伤害来平衡游戏的主要方式。这是一个开放式的系统,因为设计师有权力建立所有的东西,而不必依赖程序员。

在神秘海域2中,因为我们不断遇到我们想要针对不同类型的敌人调整不同武器的问题,我们设计了这个系统。

原本在神秘海域1中(就像我工作过的大多数游戏一样),武器对一切物件都造成了一定程度的破坏,我们通过设置物件的生命值来调整,但当涉及到平衡时,这往往会令人头痛的问题。

例如,如果你决定改变武器的伤害,那么就必须重新调整几乎所有的东西,因为你必须重新调整所有敌人的生命值,这意味着改变其他武器伤害等…

这也造成了很多混乱,因在检查调整时,敌人看起来会有随机的生命值(例如,敌人A有90生命值,但敌人B有400生命值!)

为了解决这个问题,我们创建了Damage Receiver Class系统。 它从设计人员可以设置的简单电子表格开始,然后运行Python脚本将其转换为我们的游戏脚本。 它看起来像这样:

2018-06-07-17-14-05-20186717146

这些列表示武器名称(这些是设计者在别处设置的底层名称),而这些行代表不同的Damage Receiver Classes。每行和每列的交集表示特定的武器对特定的Damage Receiver Classes会造成多少伤害。 因此,以电子表格为例,“pistol-semi-a”(即Defender手枪)将对任何具有“light-class”的Damage Receiver Class造成34的伤害,对任何具有“medium-class” 的Damage Receiver Class造成17的伤害。我们可以根据需要创建尽可能多的Damage Receiver Classes,并相应地分配它们(而不仅仅是AI)。这使得平衡游戏非常直接和简单。

武器技能ID

这就是AI如何理解他们获得的武器以及它应该如何运作。这是一个简单的结构,用于定义武器在精度,损坏和发射模式方面的表现。我们有目的地分离了玩家的这些参数版本,以便我们可以定制敌人对任何特定武器的有效性。以下是它看起来像什么:

(new ai-weapon-skill
:weapon ‘assault-rifle-b
:type (ai-weapon-anim-type machine-gun)
;; damage parms
:character-shot-damage 5
:object-shot-damage 120
;; rate of fire parms
:initial-sequence-delay (rangeval 0.0 0.0)
:num-bursts-per-sequence (rangeval-int 10000 10000)
:auto-burst-delay (rangeval 0.4 0.8)
:auto-burst-shot-count (rangeval-int 3 5)
:single-burst-chance 0.33
:single-burst-delay (rangeval 0.4 0.8)
:single-burst-shot-count (rangeval-int 1 3)
:single-burst-fire-rate (rangeval 0.16 0.20)
;; accuracy parms
:accuracy-curve accuracy-assault-rifle-upgrade
:time-to-accurate-cover 3.5
:accuracy-cover-best 1.0
:accuracy-cover-worst 0.0
:accuracy-running 0.9
:accuracy-rolling 0.5
:accuracy-standing 1.0
:master-accuracy-multiplier 1.0
:master-accuracy-additive 0.1
)

顶部有一些关于视觉效果的关键信息。Weapon参数引用武器的内部游戏名称,以便让它知道引入的美术,FX和声音。Type参数设置要使用的动画(手枪,机关枪或霰弹枪)。 我认为的伤害部分是自我解释的,我们再次使用100的基本生命值。

Rate Of Fire参数中 定义AI将如何使用武器,正是在这里,我们设置了射击模式。 在设置这些时,我们必须记住几个关键问题。第一个是子弹的实际体积,因为这会影响玩家的损伤程度。其次是武器的实际行为(即确保全自动武器的行为等)。

第三个是如何在战斗中感知音频。这是一个我们经常试图平衡的问题。我们希望AI能够像普通人那样以现实中的方式发射武器,但是我们也不希望战斗场景中的每个AI都会在没有任何停顿的情况下发射全自动武器。

它不仅感觉不对,而且打破了沉浸感,它听起来简直太可怕了!许多武器的嗡嗡声一下子充斥着整个系统,这不是激烈的交火,你会听到扭曲的噪音,这也使得玩家更难以确定敌人使用什么武器。

Rate Of Fire参数的工作方式是,在每个序列之间存在着一个有着可选的延迟时间的开火序列(在这种情况下延迟没有被使用)。 一个开火序列由多个爆发组成(在这种情况下数量设置为10000),并且每个爆发可以是全自动的(在这种情况下它使用武器设置的发射速率)或者一组具有手动输入的单次发射频率。

因此,在上述情况下,每次爆发有33%的几率成为一组单发点射,其中以0.16 - 0.2秒的速率点射,并在下一次爆发之前延迟0.4-0.8秒。否则它将是一个由3-5个子弹组成的全自动爆发,并且在下一次爆发之前延迟0.4-8秒。精度曲线指向一个预定义的结构,如下所示:

(define accuracy-assault-rifle-upgrade
(make-ai-accuracy-curve
([meters 60.0] [chance-to-hit 0.0])
([meters 30.0] [chance-to-hit 0.3])
([meters 20.0] [chance-to-hit 0.4])
([meters 12.0] [chance-to-hit 0.4])
([meters 8.0] [chance-to-hit 0.5])
([meters 4.0] [chance-to-hit 0.9])
)
)

它读取的方式是图形上的一组点,用于定义武器在指定的期望距离处的精度,并在每个点之间建立线性斜坡。 所以在这种情况下,从0到4米有90%的击中机会,然后下降到8米,有50%的击中机会,然后下降到12米,这有40%的几率击中等……我们有意地单独设置这些精度曲线,以便我们可以轻松地将它们重复用于我们选择的任意数量的武器技能。

其余的参数是影响准确性的修饰符,应该大部分是自我解释的。我确信你想知道的是Time To Accurate Cover部分。 我们这样做可以给玩家,在他们探出掩体射击时,一个小小的机会窗口。它将按Accuracy Cover Worst(本例中为0%)中列出的百分比降低AI的当前精度,然后在Time To Accurate Cover(在此情况下为3.5秒)中设置的持续时间内,将精度提高Accuracy Cover Best(在这种情况下为100%)。

因此,在这种情况下,玩家的有效效果是当玩家探出掩体射击时,他们有3.5秒的时间,在这段时间内AI的准确性将从0%返回到当前条件的基本水平。

通过使用这些武器技能定义,我们能够使AI的不同类型和类别或多或少具有挑战性。 举个例子,对于低级别士兵总体而言,我们给了他们稍慢射击频率和更长的时间Time To Accurate Cover,以使它们更容易。

而中等级别的士兵,我们会增加他们的射击频率,通过调整Master Accuracy Additive增加他们的准确率10%,并减少他们的Time To Accurate Cover,使他们更坚强。我们还会尝试调整不同武器的发射速率,使它们听起来更独特,以便玩家更容易识别(即FAL将具有与AK和M4不同的模式)。

瞄准

AI有一个权重系统来确定如何选择最佳可用目标。权重在我们的一个结构化脚本文件中设置。在游戏中,根据这些权重评估所有潜在目标,并选择权重最高的目标。以下是默认设置的样式,以及有关基本参数的一些注释以及它们的含义:

(new ai-targeting-params
:min-distance 0.0 ;; minimum distance to look for a target
:max-distance 200.0 ;; maximum distance to look for a target
:distance-weight 50.0 ;; weight to apply, scaled according to distance away

:target-eval-rate 1.0 ;; how often to evaluate targets, in seconds

:visibility-weight 10.0 ;; weight applied if the target is visible

:sticky-factor 10.0 ;; weight applied to the existing target
:player-weight 10.0 ;; weight applied if the target is the player
:last-shot-me-weight 20.0 ;; weight applied if the target shot me
:targeting-me-weight 0.0 ;; weight applied if the target is targeting me

:close-range-distance 11.0 ;; weight applied if target is within the specified distance
:close-range-bonus 0.0

:relative-distance-weight 10.0 ;; explained later
:relative-search-radius 100.0

:relative-dog-pile-weight -1.0 ;; explained later

;; weights for specific vulnerability states, explained later
:vuln-weight-cover 0.0
:vuln-weight-peek 0.0
:vuln-weight-blind-fire-cover 0.0
:vuln-weight-roll 0.0
:vuln-weight-run 10.0
:vuln-weight-aim-move 20.0
:vuln-weight-standing 20.0

:in-melee-bonus 0.0 ;; weight applied if target is in melee
:preferred-target-weight 100.0 ;; explained later
)

游戏中的大部分AI都使用这一默认的瞄准参数。这些设置用简单的术语表达的意思就是这样:

他们将寻找远至200米的目标,偏向更接近的目标。他们也会更偏向:他们可以看到的目标(visibility-weight);射中他们的目标(last-shot-me-weight)或者是玩家(player-weight)。他们也会偏向他们已经瞄准的目标(sticky-factor),并且会重新评估他们是否应该每秒选择一个不同的目标(target- eval -rate)。

我们可以使用一些参数来帮助分散多个敌人的瞄准。例如,当多个派别之间发生更大的战斗时,我们不希望每个人都瞄准同一个人。

根据同一团队中有多少其他AI瞄准了同一个特定敌人,应用 relative-dog-pile-weight(因此为什么这是一个负值)。指定的值会针对当前针对该敌人的每个团队成员的权重相乘得到总权重(因此,针对该敌人的团队成员越多,整体权重就越强)。

relative-distance-weight用于帮助根据与所选目标的距离确定优先级。它搜索在指定的relative-search-radius内瞄准相同目标的AI成员团队成员,并根据最接近该目标的人员缩放relative-distance-weight。 这有助于解决同一团队挑选他们距离最远的目标AI的问题,因为其他团队成员更接近。

vulnerability weights用于帮助根据特定条件提高定位。 所以在某些情况下会有加权,如当目标在空旷处奔跑,在空旷处瞄准射击(这只会影响玩家)以及在空旷处站出来。

preferred-target-weight是设计人员指定特定目标的一种方法。它的工作方式是我们随时可以选择指定某项作为任何特定AI的首选目标。这意味着当AI执行目标评估时,标记为该AI的首选目标的任何内容都将获得此额外权重作为评估的一部分。

所以你可以看到我们有很多选择来影响AI如何选择他们的目标。我们可以根据自己的喜好设置多种定位参数,并将它们分配给各种原型,甚至可以将其分配给不同的原型,甚至关卡的指定AI。 此外,许多这些权重可以设置为负值,因此根据场景的上下文给予我们更多的灵活性。

这是一个原型!

所有这些都构成了AI原型!还有其他参数在本文中未涉及(如测试或特定于原型的参数),但这些参数是所使用的大部分参数。通过创建这些参数的组合,我们可以创建行为不同的AI类型,并快速创建新想法的原型。当我们需要新的技能或特定的行为时,大多数决定权也在设计人员手中,只需要程序员干预(这对原型也很快,感谢技能列表)。 那么让我们继续讨论如何设置其余部分。

功能美学

当设置AI的外观(包括视觉和动画)时,我们也有很大的灵活性.对于视觉效果,我们有一个基于零件的“外观”系统,可以让我们按照自己的意愿划分角色。

例如,对于轻型和中型敌人,我们有一个基本的身体(没有手或头),各种头部(包括双手以保持肤色匹配),以及我们可以附带的一系列装备,但我们希望。在脚本文件中,我们会将“外观”定义为这些项目的特定集合,然后将它们分配给原型。

你也可以创建一个集合,然后将整个集合附加到另一个集合。我们广泛使用这个特性来创建可以随机替换的头元素。举例来说,我们有几个级别的人具有特定的装备(如特定类型的帽子或面具)。我们会为他们的装备创建几个集合,然后在AI产生时会随机选择其中一个组合用于外观。

对于动画,我们有一个系统,可以让我们随时重新映射任何动画,这样我们就可以混合搭配任何我们需要的动画。这意味着当AI系统调用某些动作时,我们可以将任何动作映射到我们选择的任何动画。

这是非常强大和灵活的,因为您不必为每个角色创建一个完整的动画集。相反,你可以将特定操作重新映射到新动画。

作为一个例子,在神秘海域2我们在轻型和中型士兵之间在如何从掩体中射击存在着差异,轻型家伙会暴露自己更多,而中型家伙则不会。我们只是使用了一个重映射,这样当AI系统发出一个命令从掩体射击时,它将为轻中型士兵使用不同的动画。

我们使用这个系统的其他例子是护送受伤的摄影师杰夫穿过小巷的顺序以及在沼泽地的古庙里,当德雷克举着一个燃烧着的火炬走动时。

思维机器

所以让我们来看看决策过程是如何工作的,以及我们作为设计师与他们交互以获得我们想要的行为。

乔治去了哪条路?

AI必须了解环境,才能让他们四处走动并做出酷炫的事情。为此,我们创建了我们所谓的导航网格(简称navmesh),它定义了AI的世界边界。这是一个在Charter中创建的多边形网格,使用一组特殊的工具来使其快速直观。

你可以在前一篇文章中找到更多关于Charter的信息

2018-06-08-11-44-03-20186811445

当我们最初在Charter内部放置一个navmesh时,这是基本navmesh的开始。我们对 navmeshes有一个特殊的编辑模式,你可以在每个顶点看到黄色光盘。

2018-06-08-11-46-14-201868114615

这些光盘让我们只需在水平面上拖动一个顶点,同时保持其与地面的高度关系。如果我们需要调整高度,每个顶点上的绿色箭头可以让我们垂直移动它。

2018-06-08-11-46-37-201868114637

我们可以通过点击连接现有顶点的红线来创建新的顶点。 我们也可以通过点击黄色圆盘中心的橙色圆圈来删除一个顶点。

2018-06-08-11-47-09-201868114710

我们可以通过在navmesh中间点击并拖动来切出一个洞。然后可以通过拖拽它的顶点并正常添加或移除顶点来修改该洞的形状。 使用这些工具,我们可以创建和操作navmesh,以符合我们希望AI导航的区域。我们还可以通过将多个顶点彼此咬合将多个导航链接在一起,编译时将它们组合到一个navmesh中 。

虽然navmesh定义了可导航空间的边界,但AI依赖于第二个与此导航结合使用的系统。 所述 navmap 是在围绕AI横轴二维网格投影。它考虑了navmesh以及动态对象。

2018-06-08-11-50-50-201868115050

在这张图片中,您可以看到所选AI的navmap(靠近中心的,周围有圆圈)。 你可以看到世界上由栅格所覆盖,并且一些栅格的正方形以黄色着色,黄色代表不可导航的空间。 使用navmesh来查找世界边界(例如物理结构周围的区域),以及动态对象(如其他AI )的navblockers。

navblocker是navmap专门读取的并且可动态改变。它通常来自对象的碰撞边界,但也可以手动放置在Charter中,也可以通过代码中的特定设置(例如使用其他AI)生成。 这使设计师能够在游戏进行中灵活地动态阻隔游戏区域。同样,通过使用这种系统,我们节省了计算开支,因为AI不需要持续探测环境中的动态障碍物。

这个系统处理了大部分让AI在环境中正确导航的繁重工作,但是当你希望AI能够在更复杂的景观中跟随玩家时该怎么办? 为此,我们有所谓的遍历动作包(TAP)。 我们创建符合环境要求的动画(例如攀登墙壁,跳过空隙,爬梯等),然后插入TAPs系统并将其放入Charter中。然后,AI可以使用这些从navmesh导航到navmesh,能够较好地跟随玩家。

影响之下

虽然navmesh和navmap给了AI对环境的理解,但他们仍需要一种方法来评估空间,并挑选最适合当前情形的指定位置。为此,我们使用我们的Combat Behaviors 系统。这是选择最佳指定点的位置的加权影响图,以每AI每秒一次的速率进行评估。系统考虑的整套要点基于几件事的集合:

  • 一个固定的网格点,将自己应用于世界并通过navmesh进行过滤
  • 掩体点
  • 它们的中心Zone Marker点(我稍后会介绍这些)

如何确定这些点的权重取决于我们在脚本中设置的参数。这里有一个来自神秘海域2的例子,里面有关于参数的评论:

(new ai-combat-behavior
:dist-target-attract 15.0 ;; stay this close to your target
:dist-enemy-repel 5.0 ;; do not get closer than this to your target
:dist-friend-repel 2.0 ;; do not get this close to your friends

:cover-weight 10.0 ;; prefer points that are cover
:cover-move-range 15.0 ;; how far you’ll move to get to cover
:cover-target-exclude-radius 8.0 ;; ignore covers this close to your target :cover-sticky-factor 1.0 ;; prefer a cover you’re already in

:flank-target-front 0.0 ;; prefer to be in front of your target
:flank-target-side 0.0 ;; prefer to be on the side of your target
:flank-target-rear 0.0 ;; prefer to be at the rear of your target

:target-visibility-weight 5.0 ;; prefer points that can see your target
)

尽管这些并不是我们可以使用的全部数值,但它们是最常用的一些。这是我们中距离Combat Behaviors的一个缩减例子。为了解决这个问题,使用它的AI将希望与目标保持5到15米距离,同时试图与朋友保持2米距离。他们更喜欢掩体,并可能移动15米以进入掩体,但他们不希望选择距目标8米内的掩护点。他们也会喜欢他们已经进入过的掩体,以及挑选可以看到他们目标的点。

Combat Behaviors让我们在AI的行为方式上有很大的灵活性。通过创建一个库并根据需要切换它们,我们可以考虑大多数我们需要设置的任何类型的场景。当我们有很大的战斗空间时,他们也非常方便,玩家可以采取多种路线,因为他们不依赖于玩家采取线性路径,因为他们总是评估情况并根据设置的参数选择最佳地点。但是有一些缺点需要注意我们必须解决的问题。

因为这是一个模糊的系统,所以可能会发生错误的读数,您必须小心解决。例如,根据条件,系统可能为这一次评估选择一个不同的点,然后返回到之前的点进行下一次评估。 必须做一些过滤才能使AI做出相应的反应,否则它们可能会不必要地往返。我们可以将一些额外的参数放入行为中,以帮助提高稳定性并帮助拒绝这种行为。

另一个需要牢记的重要问题是路径查找系统与Combat Behaviors 系统完全分开。行为只会选择目的地,而路径发现则会指出如何到达目的地。

例如,如果行为有要求击退敌人5米的距离,则AI仍然可以在目标5米内行进,以抵达他们的位置。 此外,该系统可能会挑选需要奇特路径的点(例如,该点恰好位于墙的对面,需要AI需要运行一段长的很绕距离才能到达)。

虽然我们已经提出了一些方法来解决这类案件,但仍然是我们努力改进的一个问题。这是一个独立的分立系统的缺点,我们必须让他们更好地共享数据。

集中

我们掌握的另一个与Combat Behaviors结合使用的工具是区域。区域由称为Zone Marker层的中的特定点指定,并且它包含半径和高度值以定义区域的边界。 任何具有区域设置的AI只会考虑落入区域内的Combat Behaviors 位置。 区域可以随时动态设置,包括设置在对象(如玩家)上。 这使我们可以根据战斗情况根据需要将AI集中到特定位置和对象。

感官视觉

AI用来制定决策的最后一个系统是它们的感官系统(视觉和听觉)。我们想改变的神秘海域1的一件事是防止AI始终知道他们的目标是在哪里。我们需要这个来介绍新的隐形游戏机制,并且让AI在战斗中看起来不那么全知。

我们提出的视觉系统是基于一组锥体和定时器。有一个外圆锥体和一个内直圆锥体。每个锥体有4个参数来定义它,它们是垂直角,水平角,范围和采集时间。

角度值决定了锥体的形状,而范围决定了它的延伸距离(超过这个距离,AI看不到)。 获取时间决定敌人必须在视锥内多久才能启动计时器。该值也沿着锥体的范围缩放,因此范围的最外边缘将是满值,并且它以线性变化越接近越短。

两个锥体和它们的计时器在发现目标时一起工作。当敌人进入外围锥体时,计时器开始倒计时(记住这是根据距离缩放的)。如果计时器到期,这表示AI认为他们可能看到了某些东西。然后他们转向干扰并尝试将干扰的位置置于其直视锥体内。如果敌方目标进入直接锥形,其计时器将开始倒计时。如果直接锥的计时器到期,那么AI将识别目标。

这个系统让AI能够脱离接触,并且让玩家能够在战斗时更具战略性。这也增加了他们像人类一样自然行为的感觉。一个很好的例子就是,当AI在攻击玩家时,他们进入一段长长的低掩体时。

在掩体内时,玩家会到达另一端,这样做时他们不会被看到。AI仍然会朝他们最后一次看到玩家的地方进行射击,因此在玩家脱离掩体时,允许玩家有一些额外的时间进行射击,而AI需要重新获得并转向玩家。

AI的单一视觉定义包含3组锥体,每组在玩游戏时用于不同的背景环境。第一组用于环境情况,第二组用于特殊情况称为预占,第三组用于战斗中。

环境情况是AI不知道该地区的敌人。这主要是AI开始遭遇潜行的(玩家)。环境被设置为具有更小的直接锥体和更长的获取时间,以允许玩家潜入周围环境。专注是在环境状态期间可以使用的一种特殊情况。

这个想法是,如果AI正在做一些他们将专注的事情,那么他们不会对周围发生的事情给予足够的关注。它们的距离相当短,而且取得时间很长。战斗是AI与他们的目标互动时使用的集合。它的设置使得获取时间要短得多,并且直接锥体的体积要大得多,以提高感知。

呼!

因此,我们如何使用一系列AI系统进行了深入的技术研究, 这 是本文的结尾。下一部分将讨论我们使用的游戏技巧和哲学,以及一些经验教训。下次见(希望不会太久!)

翻译后记

不得不说,这是一篇质量超高的文章,作者对神海2中的敌人AI的设计的描述十分详细,特别是一个射击游戏中敌人AI设计中所具有的参数到今天看也不过时。而且,收获了一些有意思的事情,不过这个也只能说是我的自嗨。比如,当初用谷歌的视频通关神海1的时候,记得谷歌就吐槽过神海1的敌人是透视眼,一个被惊动了,所有的敌人就都知道你在哪里了。

Search

    Table of Contents