(本视频转载自YouTube:视频原址)
本质上,这是一个充满劲爆的屠杀和时间膨胀的动作策略游戏(像是实时策略的战术游戏,但具备了动作游戏的刺激)。通过进入命令模式,你可以实时向你的载具发送命令,将动作速度大幅减慢,然后选择你想要执行的操作。然后,当你退出命令模式时,这些动作会呈现出爆炸性的壮观景象。在本文中,我将深入探讨我们如何使用虚幻引擎4开发出一个简洁的解决方案,从而创建了强悍的AI对手。
在时速200公里下进行决策……
《黑暗未来》的AI必须解决一系列有趣的挑战:
- 首先,它需要让车辆能够在一段通常全是碎片、其他车辆、急转弯、沟壑等的高速公路上行驶。
- 然后它必须高速地躲避障碍物(我们指的是高时速……例如在时速200公里(124英里)时!)。
- 做到这两项的同时,它还要使用车载机枪、火箭炮、地雷等,与玩家控制的车辆进行战斗。
- 最后,它必须做到以上所有这些内容,同时又具有足够的可预测性,让玩家能够针对它们制定策略,保证玩家不会感到无聊或重复。
诚然,这是一个令人望而生畏的期望!
但是在着手解决这些问题之前,它们必须会开车。《黑暗未来》使用了虚幻引擎4中车辆模拟代码的修正版本,该代码是从PhysX车辆模拟中实现的,因此车辆驾驶模型的细节非常丰富。
当然,这不是AI,所以我在这里不再赘述,但我只说这一句就够了——我们的车辆像真正的车辆那样运行——它们有油门、方向盘等等。
所以,车辆能够被驾驶。这很棒,“如何做到”也很简单:油门是一个从-1到+1的值,方向盘也是如此。就这样。
控制装备激光炮的高速车辆的经验教训
一旦我们考虑到这些问题,就会清醒地认识到,UE4中AI的内置寻路网格体功能不适用于我们的载具。它对于可以当场启动的角色来说绰绰有余,但是将该系统延伸到车辆上的效果并不理想。我们需要一些功能来帮助驾驶行为的正确运行。
虽然驾驶行为足以应付大量低细节度的实体,但是如果你要集中精力驾驶一些较大的Actor在环境中寻路,你就会看到这是多么的诡异。如果你没能感觉到异样,那可能是因为代码长度有数千行,具备许多紧密相连的行为,它们相互必须直接交流,从而为行为所达成的决策制定情境。
我们当时的首席程序员Abhishek Sagi,在Game AI Pro 2的一章中找到了解决方案,该章节名为 “Context Steering: Behavior-Driven Steering at the Macro Scale”,作者是Andrew Fray,他出色地描绘了他的团队为一款3A赛车游戏找到的解决方案。
我不会详细介绍情境驾驶(因为你可以——也应该——进行阅读,此处是他的博客全文),只是简单地解释一下……情境驾驶原则上类似于驾驶行为的实现,凭借对许多孤立的行为进行计算,然后将计算结果进行组合。在情境驾驶系统中,并不是每个行为都达成了自己的决策,并生成了结果,而是为它们本应做出的决策提供情境,这样系统就有了更多的信息来做出最终决策。
充分利用多线程
所以我们开始制作能够实现我们所称的情境行为系统(CBS)的原型。因此,我们使用“载具高级”模板启动了一个新项目,用一些障碍物拼凑了我们自己的地图,并给车辆设置了油门。
然后我们用一张蓝图写了一个快速而粗略的CBS。这张蓝图最终变得无比巨大——甚至无法进行截图。在下图中,我们的原型车正试图沿着样条曲线行驶,同时追逐着远处的目标,并同时避开障碍物。 通过蓝图描述这个解决方案,确实有助于我们对正在发生的过程进行可视化,考虑到这对我们而言是一个全新领域,这种方式提供了非常大的帮助。最后,我们花了两天多的时间,编写和迭代了这个基本的实现。
太棒了!现在我们的车辆可以驾驶了,我们将原型蓝图从测试项目中提取出来,并将其导入《黑暗未来》,然后将其连接到车辆上,一切都非常顺利!
正如你可能想象到的,这个过程的成本非常高昂。现实地说,如果不把系统效率降低到使整个事情毫无意义的程度,我们负担不起让四辆以上的车辆同时在我们的关卡中使用CBS。这行不通。
然而,我们有一个解决办法。情境驾驶非常适合多线程化,因为它的本质是具有一些小的、孤立的行为,这些行为有为了提供情境所需的设定数据量。因此,通过使用UE4的多线程API,我们编写了一个解决方案,其中每辆载具的数据集可以在游戏线程上生成,然后被卸至一个工作线程上,工作线程将运行这些行为中的数据,处理它们返回的情境,计算最终驾驶结果并传回至这个载具。
现在,在关卡中,我们可以轻松容纳20辆甚至30辆汽车,它们都运行着和以前完全一样的代码,但是来自CBS的成本可以忽略不计。自然,同时拥有30辆细节丰富、完全模拟的载具的其他成本仍然高得令人望而却步,更别提在30辆敌方车辆横行的情况下玩游戏有多么困难了,但有时原则最重要!
使用CBS导航行为树
经过数周难以置信、极富挑战的工作,我们的AI有能力……向左或向右转弯了。这太棒了!
现在它需要弄清楚它可能想要去哪里,可能想要追逐谁,导航至哪条路,向谁射击,何时射击,等等。为此,我们采用了UE4的行为树系统。
行为树是一种广泛使用的帮助AI在驾驶中制定决策的方法。尽管我们不会使用灵巧的内置功能进行导航,行为树系统仍然拥有我们需要的一切,甚至更多!
此时,我们在CBS中有三种行为:
- 规避,它会对环境进行追踪,从而发现应该规避的物体
- 追逐,它想开向给定的一个地点。
- 道路跟随,那个……不用说你也知道的。
我编写了许多自定义蓝图任务来让AI执行,我很快就能在许多事情上利用CBS。
当处于非战斗状态时,我们停用追逐,将理想的路线输入目标道路,进行道路跟随,并通过增加规避的轨迹长度,允许AI“谨慎”地对待障碍物。当处于战斗状态时,我们只需激活追逐行为,并向它输入目标车辆的位置,然后进入相应的逻辑,让它在合适的时机展开射击。
我们还决定使用环境查询系统,或称EQS,这是一种查询游戏环境并根据结果运行一组测试的简洁方式。通常情况下,它会与导航系统一起使用,你可以在其中查询一组导航点,并对它们的距离和视线等进行测试。在我们的游戏中,我们编写了一个自定义查询生成器,它会寻找给定团队中的载具(玩家、敌对AI、平民AI等),并根据接近度和方向对结果进行评分。
可以运行EQS查询来查找单个结果,或者返回所有结果,因此该查询可以同时用于简单的敌人探测和理想目标的选择。更简洁的是,EQS查询是时间分段的——它们的运行跨越了好几帧——因此你可以在不对性能造成大量影响的条件下,运行多个相对复杂的查询,只要你不需要立即获得结果。
教会AI所有关于编队的知识
现在我们的AI可以驾驶和战斗了,很明显AI还需要协调。当游戏任务要求对车队进行协同攻击时,每辆车仅仅独自漫游并享受美好时光是不足以应付这个要求的。为了解决这个问题,我们需要一个分层化的方法,让驾驶员AI来处理繁忙的驾驶和射击任务,并让控制多个驾驶员的群组AI告诉它们前往何处以及向谁射击。
这涉及到几个关键的变化——不是让驾驶员AI定位并与自己的目标交火,而是让它们把已经找到目标的消息通知给自己的群组AI。这个群组会保存一份所有已知目标的列表,并可以对目标进行优先排序,以及将目标分配回驾驶员。在标准情形中,这可能看起来像是驾驶员自己做出的决定,但是有了群组,让我们的设计人员能够在任何给定时间,限制与单一目标交火的驾驶员数量,并覆盖其他交火,优先攻击特定的目标。
它还支持编队驾驶。群组会指定特定的车辆为领头车辆,其他车辆为跟随车辆,给它们提供理想的时钟朝向(5点方向,7点方向)和距离。然后,其他驾驶员会在它们的行为树上运行一个自定义的服务节点(服务节点本质上是以自定义的时间频率运行的函数,并且只有当树上它们所在分支中的一个任务正在执行时,它才会执行),它会计算出理想的位置并将其反馈至CBS中的追踪行为。
这个特性为游戏环境中的许多巨大变化打开了大门。编队有利于保持几辆车的共同行驶,当然,它们很容易扩展成敌对编队,而且因为它们的定义很容易,所以我们能够根据队伍中的车辆类型和它们所装备的武器类型,建立大量预设编队以供使用。举个例子——如果队伍中有一辆尾部装甲很强的载具,它有一个安装在炮塔上的武器,另外还有一辆有强大撞击武器的载具,那么它可能会尝试采取一种“带路然后跟随”的队形,装甲厚的车辆在前面行驶,诱惑玩家攻击,而撞击载具从后面撞击玩家的车辆。
这张图中,你可以看到,两辆由AI控制的载具(左边、底部)试图在玩家的载具周围组成编队,而第三辆屏幕未显示的载具正在后方尾随。 漫长道路的尽头……
《黑暗未来》的创建带来了一些独特的挑战和问题,但与UE4的合作帮助我们度过了最糟糕的时期,我们最终获得了一款引以为豪的游戏。
如果你想一睹游戏风采,可以看看我们的新预告片。《黑暗未来:血腥王国》已于5月16日(星期四)发布,你可以在我们的Steam页面上找到更多细节。