转载自知乎(已授权):https://zhuanlan.zhihu.com/p/439908024(B站不支持GIF,需要观看GIF的可以移步知乎原文搬运)
这篇文章来自GDC,是由顽皮狗的游戏程序员Ming-Lun"Allen"Chou为大家分享。
视频中重点分享了《最后生还者2》中近战系统的数据分析工具以及解决和优化特定近战细节问题的组件。
通过阅读可以知道类似的近战系统中存在哪些边界情况以及设计细节,并能够看到《最后生还者2》中为了处理这些问题给出了怎样的技术设计方案,适合战斗策划和游戏程序阅读。
较多GIF,手机流量预警!!!
欢迎大家,在这里我会分享《最后生还者2》中的近战设计。我叫Allen Chou,顽皮狗的游戏程序员。
首先让我来介绍一下我们近战AI系统团队的成员。我和Sandeep Shekar共同负责这个系统的游戏编程,Christian Wohlwend负责游戏设计,Lee Davis负责近战系统中的动画。

本次演讲分享的内容:
比较《最后生还者2》与《最后生还者》以及《神秘海域4》中的近战系统
近战系统所需要的数据
近战系统中为组件服务的数据分析工具
解决优化特定近战问题的组件

首先让我们来看看《最后生还者》以及《神秘海域4》中的近战系统。


在这些顽皮狗以前发布的游戏中,近战攻击的前摇(开始攻击到攻击判定的时间)很短,没有闪避技能,NPC开始攻击基本就意味着击中,除非玩家的攻击判定更快。

我们再来看看《最后生还者2》中的差异:
NPC有更长的攻击前摇
NPC攻击前摇的视觉效果更加明显
玩家拥有闪避能力
对于玩家操作技巧要求更高


近战相对于枪战也有足够的比重
鼓励近战遭遇
有技巧的玩家可以无伤
达到顽皮狗的技术标准
一个近战攻击动作包含:
一个由角色单位播放的动画
每个近战攻击都有开始和结束的条件。比如角色是不是在范围内,是不是面朝目标方向,攻击的运动路径是否无阻挡,条件不满足不允许近战攻击。
我们在近战攻击过程中有一些事件,在动画的timeline上标记事件。比如打击关键帧,目标对象追踪帧以及特定的攻击中存在的霸体帧。
一个近战行为包含:
可选攻击动作列表,视情况选择特定攻击。比如NPC是想冲到玩家身边攻击还是稍微有一点距离的时候发动攻击。
我们有运动类型,用来配置是否可以在近战行为过程中进行移动或冲刺。
整个近战行为也有进入和离开条件。
我们有碰撞检测射线,用来反应物理和碰撞的交互信息,这是开发中很基础的检测。我们使用射线检测或者球射线检测。

这个视频中,从NPC头部或者眼睛处发射球射线至玩家角色。
我们使用层级来过滤一些碰撞。比如在碎片层级,我们不允许上面这个眼部射线检测到场景中的细碎物件。
我们也支持更细致的层级过滤,比如通过三角比特遮罩。这在处理大型碰撞体时很有用,比如夜间照明时部分区域有亮光,大型墙体上透明的区域等允许NPC看到玩家的情形。

接下来聊聊导航探针,和碰撞射线比较相似,只不过他们是在导航网格空间中处理的。
就像是2d空间中的点或圆形射线。碰撞射线遍历所有除了动态障碍以外的静态障碍,而导航探针在导航空间中遍历。一般来说,在较短距离时导航探针相比碰撞检测性能更优。我们通常用这个处理空间检测问题。
游戏玩法中的可交互几何体。他们可以是工具在碰撞体中自动生成的,或者是策划手动摆放的。
比如说玩家可以攀爬的边缘,NPC可以用来作为掩体的墙角。
在运行时我们向系统发起检测请求,比如:玩家三米范围内的所有可攀爬区域,NPC附近的掩体。

我们有随机动画分析工具,我们这个工具允许我们获取特定动画的特定帧的特定骨骼的变换数值是多少,用来分析实时的动画信息。
其中一个例子是NPC的惊吓动画。
当玩家开枪时NPC会受到惊吓并播放对应动画,在《神秘海域4》及《最后生还者》中我们只是原地播放惊吓动画并同时让NPC面向玩家。
在《最后生还者2》中我们希望行为更加地富于变化,所以NPC受到惊吓时会进行运动。但有个问题是,NPC这么做可能最后会到掩体后面去,这会让NPC看起来很蠢。

所以我们用这个随机动画分析工具的数据去分析NPC的轨迹以及执行导航探针去确保有足够的运动空间,以及计算NPC眼部到玩家的射线是否会在动画终点被障碍阻挡,这是演示视频。
NPC播放惊吓动画的同时朝右移动,你可以看到有个打向右边的绿线,这个绿线意味着NPC视线不会被阻挡,左边的红线意味着NPC视线会在动画结束时被汽车阻挡,中间这个线意味着当所有移动动画条件都不通过时使用静止动画。
现在让我们开始看看用于打磨近战系统的各种组件。
我们第一个问题是NPC应该处于玩家周围的哪个位置,同时NPC没有互相阻挡。
玩家周围有多个可选攻击槽位,NPC可以定位到其中之一。
NPC当前想要采取的攻击行为决定了NPC与玩家之间的直线距离。
为了寻找最好的攻击槽位,我们需要知道哪个槽位对于玩家来说转动的角度是最小的同时在这个方向上有足够的运动空间。

同时还有个情况需要考虑,如果NPC在障碍后面原来的攻击槽位可能不是最佳的。
为了处理这种情况,我们计算了NPC到玩家的导航路径,能够直线无障碍到达玩家位置的墙角点作为计算依据。

同时要考虑每个槽位方向上是否有足够的空间,我们在每个槽位方向上用导航探针进行检测。
最终的选择规则
我们用能够直线无障碍到达玩家位置的墙角拐点作为依据去选取攻击槽位
如果这个槽位方向上没有足够的运动空间,我们考虑旁边的槽位
示例
一只想离玩家一定距离的狗的例子。
当玩家到汽车后面以致攻击槽位被阻挡时,狗移动到了最近的一个有足够空间的槽位。
近战攻击需要目标之间近距离接触以制造伤害。我们使用导航探针去确保在开始攻击之前运动路径是无阻挡的。这是一个显而易见的处理,比较深入的处理我们称之为角落攻击运动线。
玩家和NPC挨得很近,但被墙角隔开,我们依然希望玩家可以对NPC发动近战攻击。但是攻击运动线被墙体阻挡了,被标为了红色,如果以上述逻辑作为条件,此时是不允许攻击的。
我们的做法是我们查找玩家到NPC的导航路径。如果我们发现导航路径与攻击运动线差异不大,我们认为是可以攻击的,我们让玩家移动然后击中NPC。
这有两个检查条件:
比较导航路径的路程与攻击运动线长度
将导航路径投影到垂直于攻击运动线的平面上,看导航路径向侧面偏离了多少。
如果两个条件的差异都很小,我们认为玩家此时是可以攻击的。
如果NPC在某一刻以当前面对角色的方向发起攻击,并在后续过程中顺着原生近战攻击动画的路径进行移动,玩家可以很轻松地晃掉NPC的攻击。
所以我们给了NPC在攻击过程中旋转自身以面向玩家的能力,当玩家向侧边移动时他们能更好地抓住玩家。
但当玩家成功使用了闪避技能时我们取消或中断这种目标追踪,这样强化了玩家的视觉反馈。
当玩家前后移动的时候,如果NPC依然采用原生攻击动画中的位移也会有问题。
当玩家向前走时,NPC在攻击过程中容易走过头,当玩家向后退时,NPC很容易打不到玩家。
在这些情形中我们需要额外修正NPC的移动速度。对于这个问题的解决方案我们称之为目标接触技术,这个修正称之为运动修正倍率。
IdealMovementMultiplier:运动修正倍率的理想值
ProjectedDistanceToCover:投射距离
RawRemainingDistance:原生动画的当前帧到击中帧的时间所对应的位移距离(这个变量值在上面提到的随机动画分析工具中获取)
CurrentTargetDistance:此时攻击者和目标之间的距离
RelativeSpeed:攻击者和目标的相对速度
RemainingTime:当前帧到击中帧的时间
同时为了让这个过程保持丝滑,运动修正倍率会从当前值lerp到理想值。
视频中玩家往前跑,NPC停下并进行攻击。当玩家往后退,NPC提速紧跟玩家。
玩家的差异
玩家也有这个逻辑,但是玩家采取的移动方式和NPC不同。
如果玩家攻击丢失的话负反馈是很强烈的,我们要确保在允许的情况内玩家总是能打中NPC。
我们使用玩家到NPC的导航路径,我们让玩家沿着路径移动,当玩家或NPC的位置发生变化时,保持路径的更新。不过如果在过程中NPC离得太远或者其他人挡路,我们也是会中断这个攻击的。
下一部分是顶墙攻击,顶墙攻击是将被攻击目标压在其背后的墙上的近战攻击。
分为顶着高墙的攻击以及顶着矮墙的攻击两种类型,采用何种攻击取决于目标背靠的墙有多高。

墙体探针检测
我们从近战攻击者的位置发射线以寻找附近的墙体。我们有两组射线,一组用于矮墙检测,一组用于高墙检测。
如果高墙检测组里有射线打到东西了,意味着在这条射线方向上有高墙。
如果矮墙检测组里有射线打到东西了,但是高墙检测没有打到墙或者高墙检测打到墙了但比矮墙检测要远,我们认为在这个方向上是矮墙。
一旦检测成功,我们使用检测成功点下方的墙角作为动画参考点来播放近战动画。
攻击运动空间检测
在游戏对象实际执行顶墙攻击之前,还有一些额外的检测去确保有足够的空间让近战动画完整播放。
法向:从墙壁法线方向打出圆形探针,以确保攻击者在目标前面有足够的空间。
切向:我们有两个探针沿着墙壁方向向侧面投射,正负切线方向各有一个,以确保有足够的横向空间。如果一侧射线被阻挡,即没有足够的空间,我们将动画参考点向相反的方向移动去腾出空间。如果两边检测都失败了,就意味着没有足够的横向空间,顶墙攻击就不允许执行。
我们还收集了矮墙边缘线的信息,图中的品红色线就是。为什么要收集这个信息呢?因为矮墙对应的美术动画是根据特定墙体高度制作的,而游戏中矮墙有高有低,形状不一。如果我们总是使用同样的美术动画,那结果上看是很机械的。
所以我们收集了矮墙边缘线信息,并根据这个信息垂直移动动画参考点。
从图中你可以看到,当播放动画时角色的背精确地靠在栏杆顶部,既没有太往下导致穿模,也没有太高导致模型悬空。
但是垂直地移动动画参考点有个副作用,在编辑器视角下会看到角色脚插进地里面或者悬空。我们可以使用脚部IK或者压根不处理,因为在游戏视角下你也看不到艾莉的脚,所以我们最终决定不处理。
当NPC从攻击指令列表选择一个攻击进行近战攻击时,我们要避免NPC的武器尖端插进关卡地形或者其他角色身体。
所以我们给每个可能的近战攻击动画构建了挥击区域,并收集了武器尖端的轨迹,数据同样来自于随机动画分析工具,我们将轨迹投影到导航网格上用导航探针进行探测,我们会过滤掉被网格边缘阻挡的攻击。
图中你能看到六种攻击对应的六种轨迹,只有粉红色是符合要求的,所以最后NPC使用粉红色对应的攻击方式。
不过这个不是一个硬性过滤,如果所有的近战攻击都不符合条件,我们会随机选取其中之一,因为相比潜在的视觉效果问题,攻击不出来是更加严重的。
所有的组件就聊完了,让我们快速总结一下。
先介绍了运行时使用的分析工具,后介绍了解决或者优化特定近战攻击问题的组件。
分析工具帮助我们把游戏内的数据可视化,分析工具对于后面解决具体问题的组件特性来说是必不可少的。这两者共同作用让《最后生还者2》满足了顽皮狗的高要求。

我希望这次演讲对你们有帮助,同时我们也在招人,谢谢大家。