在今年的虚幻开放日(12月2-3日)上,eBrain Studio负责人李伟就《生死轮回》以及战斗和随机地图系统的开发、设计和执行进行了演讲。以下是经过编辑的演讲内容:我叫李伟,是eBrain工作室的总监。我和我的好友正在开发一款基于Unreal Engine 4的横版Cyberpunk动作Roguelite游戏,名为《Circle of Life and Death》。这是一款带有战斗、机制和谜题的故事驱动游戏,即将面向PC和主机发行。在游戏开发过程中,我担任制作人。主要负责编剧、设计、玩法编程。在此之前,我是Orap Games的首席执行官和制作人,曾在UDK的《Dying Days》和Unreal Engine 3的《Ninja Turtle Online》中担任同样的职务。今天我将讨论《生死轮回》中的“战斗系统”和“随机地图系统”两部分内容。对于这两个系统讨论我们如何从设计到实现,遇到和解决问题,完成并最终完善和扩展。
作战系统
作为一款动作游戏,“战斗系统”的良好呈现是游戏质量的关键。然而,“战斗系统”是一个非常普遍的主题,因为围绕着战斗系统存在着太多的模块,并且其边界通常都是模糊的。所有的细节都太大了,无法一一涵盖,所以在这里我选择了“Melee weapons”和“Victim feedback”这两个核心部分进行展示。
我将用设计的思维方式,系统的列出,然后逐一详细的讨论它们的技术实现。
近战武器设计1:技术目标
《生命与死亡的循环》的基本玩法允许你使用各种近战武器与敌人战斗。丰富游戏体验并推广为了追求战斗,我们设计了超过30种不同的近战武器,具有不同的特点。你可以看到武士刀、大锤、长棍、拳头和其他近战武器。
如何实现武器的基本毁伤功能,打开不同武器的感觉差异是我们技术实现的目标。基于这一目标,我们分析了实现上述目标所需要的功能。
近战武器设计2:特征分析
我们从近战武器的特点开始:
(1)武器形状:每种武器都有不同大小的形状。我们需要准确地反映波的测试结果。允许设计师根据武器的形状调整攻击探测的范围。
(2)目标角色反馈:每个攻击角色都会给出不同的反馈。如果人类流血,机器人就会发出火花。敌人也有不同的死亡效果。例如,如果我们想要成为硬核玩家和现实玩家,那么用钝器杀死敌人就会产生Rag Doll效果,而锋利的武器则会切断敌人的四肢。
(3)表面材料反馈:除了击中角色。我们想要像《黑暗之魂》那样,拥有足够的细节,当武器击中墙壁时,它就会发出火花。
黑暗的灵魂撞墙了
(4)利器和钝器:利器和钝器有不同的冲击感觉,武士刀和棒球棒击中目标时的感觉无疑是不同的。前者类似于切一个甜瓜,而后者在击中目标时感到阻力。
武士刀和棒球棒
近战武器架
有了以上的考虑和问题,让我们来谈谈近战武器系统每个环节的具体技术实现。
生死循环的玩法功能主要是在c++中实现的,当涉及到视觉配置时,这对蓝图的子类是开放的。
武器类c++代码
武器类蓝图代码
这样做的好处是,c++可以轻松而有效地实现算法和函数。蓝图可以提供强大的可视化定制和直观的调用逻辑。武器系统就是以这种方式实现的。对吴类,其父类继承自AActor。
我们在c++中创建了skeleton meshcomponent,这样就可以很容易地在代码中访问它来实现损伤算法,比如线性检测。
武器模型和它的物理设置在蓝图中,这样设计师就可以自定义击中粒子反馈,插槽和参数。为武器的骨架网格创建一个槽。骨槽可以用来指定每个武器的探测开始和结束范围。
刀的近战武器槽
棍子近战武器插槽
现在我们来谈谈近战武器攻击检测的逻辑。
近距离战斗武器检测1:线性检测
当一件近战武器被挥舞时,它会不断地从狭槽的一端向目标发射射线,检测所遇到物体的扫描。
武器目标检测:虚幻引擎4提供了各种线性检测api,可以在两点之间发射射线,并根据效率和需求返回扫描对象信息。例如,我们使用这个线性检测函数并定制它,
简单地看一下这个函数,我们可以在这个函数的结果中返回几个重要的参数:
-数组结构tarray&outhits返回扫描对象的列表。有一些参数可以让我们得到更多的细节,我们稍后会讲到。
- Const fvector和Start, Const fvector和End可以传递到武器槽的开始和结束。
这两个参数为我们刚才提到的需求分析提供了最基本的信息。OutHits能够帮助我们基于这些信息去设置反馈粒子,声音等等。开始和结束向量允许我们的设计器传入已建立的槽位置信息,以设置线性检测的范围。
虚幻引擎4提供了许多可视化效果Bug工具中,如果你想要看到这条射线的检测,你可以使用DrawDebugline函数来查看。
播放器启用调试的线性检测效果
近战武器检测实现2:角色驱动检测通知
毫无疑问,最自然的逻辑是角色在使用武器时进行检查。线性检测本身是性能密集型的,根据执行情况启用和禁用用户的攻击动画。如下,我们定义攻击检测通知节点,并在攻击动画播放时调用代码,从而控制武器检测启动TraceStart和结束TraceEnd。
通知玩家的攻击动画AnimNotify
当检测开始时,在此期间将持续跟踪。这是因为跟踪可以写入Tick中并逐帧执行,或者可以定义一个Timer来根据特定的高频间隔检测跟踪。频率越高,检测越准确,但会消耗能量。频率越低,检测精度越低,但节省性能,可以在这里选择。
玩家的调试线很稀疏
从理论上讲,我们只需要识别返回结果队列中追踪到的敌人,并从中抽血,从而实现损伤检测。在这里,我们有一个调用ApplyPointDamage的武器来将伤害传递给目标,而目标本身会执行实际的处理。
然而,如果你这样做,你将会犯一个严重的错误。你可能会发现,只要挥一挥武器,敌人就能承受多次攻击,直到死亡。这就引出了命中队列的问题。
正如我们在上面提到的,在Trace过程中可能会多次检测到相同的敌人,并且会多次被破坏。我们只希望同一种敌人每次都能受到一种攻击。为了正确地做到这一点,这次我们需要设置一个队列来显示TraceStaRt到TraceEnd的目标,添加的目标将被重新加权。
在同一攻击动画中,明确一次攻击和多次攻击之间的区别是很重要的。如果你想在一个动画中造成两个伤害,再次调用TraceStart和TraceEnd。
为什么会有两种或两种以上的情况,比如下面的矛旋攻击。我们希望在这个动画里的矛每半回合造成一次伤害。这让动画师能够根据自己的需要创造出完整的动画,并让设计师能够根据自己的需要设置伤害规则。
当使用矛时蒙太奇旋转动画
攻击反馈达到1:击中目标
在上面的代码中,我们可以看到如何判断敌人是否被击中并处理它。
IsInHurtList就是我刚才讲的。在这个TraceStart和TraceEnd中,我们对同一个扫描目标进行一次判断并执行加权。IsIgnoreByTeamID用于避免友方火力,因为我们不希望敌人互相攻击。
近战武器攻击反馈执行2:血溅和脆金属
此外,HitResult还可以为我们返回物理材料。物理材料定义了材料表面的属性,并相应地设置了相应的反馈效果。如果我们撞到水泥地,就能送回烟雾。木头是锯末。我们可以在武器中细化打击不同物理材料的反馈效果。
我们能够击中的子弹将会击中粒子,这取决于物理物质。同样,当角色移动时,他的脚步会在地面上进行线性检测,判断物理材质,并反馈相应的声音。
谈谈相机抖动和手柄振动。虚幻引擎4为我们封装了很多功能,我们的玩家角色控制器继承自PlayerController,在这个类中,为开发者我们提供相机振动的功能。
我们只需要用密码打电话,挥动武器,击中敌人的位置。然后,对应的CameraShake变量将暴露在c++的蓝图中,这样设计师就可以根据攻击的感觉调整武器的冲击。制作不同的武器。
武器击中目标后摄像头会震动
我们不仅要在打击目标时添加摄像机振动,设计师还可以在挥杆开始时为每种武器定制摄像机振动。
如上所述,我们希望像武士刀和钝棒球棒这样的锋利物体在击中敌人时能够做出不同的反应。你是怎么做到的呢?从理论上讲,这意味着在你击中敌人的那一刻停止系统。以Capcom的《街头霸王》为例:
虚幻引擎4的强大库,再一次帮助了我们,在gameplaystatic中封装了以下函数。H头。这个函数设置整个游戏世界的时间播放速率。
当我们击中目标,我们就拖延它,为每种武器设定一个拖延时间。同时也要将这些参数呈现给设计师,他们可以根据每种武器设置攻击敌人的暂停率和持续时间。让不同的武器在攻击时产生不同的感觉。你可以用肉眼看到下面的武士刀和大锤有不同的感觉。
它在代码中的工作方式是,当武器线性检测到敌人的攻击时,系统就会减速。在很短的时间后,恢复正常。根据不同武器(如锋利武器和钝器)的特性,减速的速度和停滞的时间可能会有所不同。
正如我们在上面看到的,为了提供近战武器击中目标的反馈,我们在武器上增加了许多功能。探戈需要两个人,我们需要给那些被击中的人反馈。我们想用三种方式来展示命中的效果:第一种是给命中目标一定的推力,如下所示。
如你所见,空无一物在《洞穴骑士》中刺向敌人,使攻击变得非常强大。一方面,推力增强了玩家的输出力反馈,这非常适合于横向卷轴游戏。
另一方面,我们可以通过让主角在移动之间介入来动画主角的攻击。玩家不断向前推进,而敌人则会受到攻击并后退,这种与对方同步的感觉很棒。34、打人是为了感觉良好,所以打人会有一种压力感。
第二个是热门动画。敌人在受到攻击时执行命中动画是最自然和直接的刺激反馈。第三是从受害者的身体和周围的墙壁上溅出的血。毫无疑问,这增加了细节感。细节是我们要追求的。稍后您将看到为了显示细节,我们实现了多少有趣的特性