十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

UE5战斗系统开发实战:从连击判定到伤害反馈的完整实现

UE5战斗系统开发实战:从连击判定到伤害反馈的完整实现 在虚幻引擎5UE5中构建一个手感扎实、反馈清晰的战斗系统是许多动作游戏开发者的核心目标。一个优秀的战斗系统不仅仅是动画的播放它需要精确的连击判定、可靠的命中检测以及即时的伤害反馈这三者共同构成了玩家操作与游戏世界交互的核心循环。对于已经熟悉UE5基础操作希望深入游戏玩法编程的开发者而言理解如何从蓝图或C层面实现这套机制是迈向专业游戏开发的关键一步。本文将以UE5.7版本为环境实战演示如何构建一个包含基础连击、基于碰撞盒的命中检测以及多层次伤害反馈的战斗系统。我们将从角色动画状态机的设计开始逐步深入到攻击动画蒙太奇Montage的触发、攻击碰撞体的动态激活与检测最后完成伤害数值显示、受击动画以及屏幕特效等反馈链。无论你是使用蓝图进行快速原型验证还是倾向于C实现更可控的逻辑本文提供的设计思路和实现细节都能为你提供清晰的路径。1. 理解战斗系统的核心组件与工作流在动手写第一行代码或连接第一个蓝图节点之前必须理清战斗系统中几个核心组件是如何协同工作的。一个典型的近战战斗流程可以抽象为玩家输入 - 角色状态判断 - 播放攻击动画并激活攻击碰撞体 - 碰撞检测 - 应用伤害与触发反馈。1.1 状态驱动动画蓝图与状态机战斗行为高度依赖于角色的状态。你不能在角色翻滚时触发重击也不能在倒地时继续连击。因此所有战斗逻辑的起点是角色的动画蓝图Animation Blueprint及其中的状态机。通常我们会有一个主状态机包含“空闲Idle”、“移动Movement”、“跳跃Jump”以及关键的“攻击Attack”等状态。攻击状态本身通常也是一个子状态机用于管理连击的不同阶段如Attack_1, Attack_2, Attack_3。状态转换的条件不仅仅是动画是否播放完毕更重要的是由游戏逻辑层如角色类设置的布尔变量如bCanCombo、bIsAttacking或事件如ComboCheck事件。这种设计将动画表现与逻辑判断分离逻辑层决定“何时可以连击”动画层负责“播放对应的连击动画”。1.2 攻击检测碰撞体与查询时机命中检测是战斗系统的“裁判”。在UE中最常用的近战检测方式是使用碰撞盒Box Collision或胶囊体Capsule Collision。这些碰撞体通常作为骨骼网格体Skeletal Mesh的套接字Socket附加在武器骨骼如hand_r_socket或角色骨骼如palm_r上。关键在于碰撞体不应始终启用。它只应在攻击动画的特定帧即武器的挥砍轨迹与目标可能相交的时段被激活。这通常通过在攻击动画蒙太奇中设置动画通知Animation Notify来实现。例如在动画的第15帧设置一个NotifyBegin通知来激活碰撞体在第25帧设置一个NotifyEnd通知来关闭它。这样可以确保检测的精确性避免在收招阶段误伤或无法击中。检测逻辑本身可以在角色类或一个专门的“武器”Actor组件中实现。当碰撞体启用并与其他角色的碰撞体重叠Overlap时即触发命中事件。1.3 反馈链条从数据到表现命中发生后系统需要产生一系列反馈让玩家和受击者都感受到这一击的份量。这是一个多层级的链条逻辑层计算伤害。这可能涉及攻击者的攻击力、受击者的防御力、命中部位倍率等。受击者层应用伤害调用ApplyDamage播放受击动画蒙太奇触发受击音效可能还会产生受击硬直或击退效果。攻击者层播放命中停顿Hit Pause效果、镜头震动Camera Shake、命中音效。UI层在命中位置或屏幕固定位置显示伤害数字Damage Number。特效层在命中点生成粒子特效如火花、血雾。2. 项目环境准备与基础资产设置我们从一个第三人称模板项目开始。确保你的虚幻引擎版本为5.7或相近版本因为某些节点和API可能有细微差别。2.1 创建项目与角色启动UE5.7选择“游戏Games”模板类别然后选择“第三人称Third Person”。项目设置中使用蓝图或C均可本文将以蓝图为主并提示关键C节点。打开项目后找到内容浏览器中的ThirdPersonCharacter蓝图通常位于Content/ThirdPerson/Blueprints/。我们将其复制一份并重命名为BP_CombatCharacter作为我们战斗系统的主角。同样找到ThirdPerson/Animations目录下的动画蓝图TP_AnimBP也复制一份并重命名为ABP_CombatCharacter将其分配给我们的BP_CombatCharacter的网格体。2.2 导入攻击动画与配置蒙太奇你需要一套攻击动画序列Animation Sequences。可以从市场购买或使用Mixamo等工具制作后导入。假设我们有三段连击动画Attack_Start、Attack_Mid、Attack_End。在内容浏览器中右键选择“动画(Animation)” - “动画蒙太奇(Animation Montage)”。命名为AM_ComboAttack。打开AM_ComboAttack将三段攻击动画序列依次拖入蒙太奇轨道。调整它们的位置使其首尾相接。关键步骤添加动画通知轨道。在蒙太奇编辑器的“轨道Tracks”面板为骨骼添加一个“通知轨道Notifies Track”。我们将在此轨道上放置控制碰撞体和连击的逻辑通知。在第一段动画 (Attack_Start) 的挥刀起始帧添加一个通知命名为Notify_EnableHitCollision。在挥刀结束帧添加一个通知命名为Notify_DisableHitCollision。在Attack_Start动画即将结束但下一段Attack_Mid开始前例如最后5-10帧添加一个通知命名为Notify_ComboWindowOpen。这是连击输入的“窗口期”。在Attack_Mid和Attack_End动画中重复上述过程注意连击窗口通知只在非最后一段攻击中存在。2.3 设置攻击碰撞体打开BP_CombatCharacter的角色蓝图。在组件面板添加一个“盒体碰撞Box Collision”组件。将其重命名为HitCollisionBox。将HitCollisionBox附加Attach to到角色的骨骼网格体组件上并选择套接字为武器骨骼如hand_r_socket。调整盒体的位置、旋转和大小使其大致匹配武器挥砍的轨迹。在细节面板中找到“碰撞Collision”部分设置“碰撞预设Collision Presets”为“自定义Custom”。“碰撞启用Collision Enabled”设为“查询专用Query Only”。“对象类型Object Type”设为“世界动态WorldDynamic”。在“响应Responses”中将“世界动态WorldDynamic”和“世界静态WorldStatic”等的碰撞Collision响应全部设为“忽略Ignore”只保留“重叠Overlap”响应。我们主要关心与“Pawn”或“角色”的重叠事件。3. 实现连击系统状态与输入管理连击系统的核心是管理玩家的攻击输入与角色攻击状态的同步确保在正确的时机接受输入并切换到下一段攻击。3.1 在动画蓝图中构建攻击状态机打开ABP_CombatCharacter动画蓝图。在动画图表AnimGraph中确保有一个“状态机State Machine”节点连接到最终动画姿势。双击进入状态机创建以下状态Idle/Walk、Jump、Attack。进入Attack状态这本身应该是一个子状态机。在其中创建三个状态Combo1、Combo2、Combo3分别对应三段连击动画。设置状态转换规则从Idle/Walk进入Attack子状态机的Combo1条件是bIsAttacking为真。在Attack子状态机内部Combo1-Combo2条件是bCanCombo为真并且bComboPressed为真表示玩家在窗口期内按下了攻击键。Combo2-Combo3条件同上。从任何攻击状态退出到Idle/Walk条件是bIsAttacking为假。这些布尔变量bIsAttacking,bCanCombo,bComboPressed需要在角色蓝图BP_CombatCharacter中定义和更新。3.2 在角色蓝图中编写攻击逻辑打开BP_CombatCharacter的事件图表Event Graph。定义变量bIsAttacking(布尔型)角色是否正在攻击。bCanCombo(布尔型)当前是否处于可以触发下一段连击的窗口期。bComboPressed(布尔型)玩家是否在窗口期内按下了攻击键用于缓存输入。CurrentComboIndex(整数型)当前连击段数1, 2, 3。AttackMontage(动画蒙太奇对象引用)指向我们创建的AM_ComboAttack。处理攻击输入找到已有的“输入动作 IA_Jump”等事件节点。添加一个“输入动作InputAction”事件绑定到你的攻击键如鼠标左键。在此攻击输入事件的逻辑中首先判断bIsAttacking。如果为假说明是第一次攻击。设置bIsAttacking为真CurrentComboIndex为1然后播放蒙太奇AM_ComboAttack。同时设置一个延迟在连击窗口通知的大概时间后将bCanCombo设为真。如果为真说明角色已在攻击中。此时不直接触发新攻击而是将bComboPressed设为真。这个变量将在动画通知Notify_ComboWindowOpen被触发时检查。响应动画通知我们需要在角色蓝图中创建与蒙太奇里同名的动画通知函数。在“我的蓝图My Blueprint”面板的“函数Functions”部分点击“重载Override”按钮选择“动画通知Anim Notify”相关函数。UE5.7中更常用的是“事件Event”-“添加自定义事件Add Custom Event…”然后将其与蒙太奇中的通知绑定。更规范的做法是使用“动画通知状态Anim Notify State”或“动画通知Anim Notify”并在蓝图中重载ReceiveNotify函数。对于初学者一个更直观的方法是在角色蓝图中创建三个自定义事件EnableHit、DisableHit、ComboWindowOpen。然后在AM_ComboAttack蒙太奇中将之前添加的Notify_EnableHitCollision、Notify_DisableHitCollision、Notify_ComboWindowOpen通知的“通知类Notify Class”设置为“蓝图通知BlueprintNotify”并在“通知Notify”中分别调用我们创建的那三个自定义事件。实现通知事件逻辑EnableHit事件设置HitCollisionBox组件的“生成重叠事件Generate Overlap Events”为真。DisableHit事件设置HitCollisionBox组件的“生成重叠事件”为假并清除已重叠的演员列表避免同一段攻击内重复命中。ComboWindowOpen事件这是连击系统的核心。// 伪代码逻辑 设置 bCanCombo 为 True 检查 bComboPressed 是否为 True 如果为 True: 设置 bComboPressed 为 False 设置 bCanCombo 为 False CurrentComboIndex 增加 1 // 使用蒙太奇的“跳转节Jump to Section”节点跳转到对应连击段的动画节如“Attack2” 跳转蒙太奇节到名称(例如: Attack CurrentComboIndex) 否则: // 玩家没有在窗口期内按键设置一个定时器在窗口期结束后关闭连击机会 设置一个定时器0.1秒后执行设置 bCanCombo 为 False攻击结束重置在AM_ComboAttack蒙太奇的最后一帧或通过动画通知Notify_AttackEnd触发一个事件来重置所有状态bIsAttacking False,bCanCombo False,bComboPressed False,CurrentComboIndex 0。4. 实现命中检测与伤害计算当碰撞体启用并与敌人重叠时我们需要检测并处理命中。4.1 配置碰撞事件在BP_CombatCharacter的HitCollisionBox组件细节面板或者在其事件图表中添加“组件开始重叠时On Component Begin Overlap”事件。在此事件中首先获取重叠的其他组件Other Comp及其所有者Other Actor。进行一系列过滤检查避免无效命中检查Other Actor是否等于自身Self是则返回。检查Other Actor是否已经存在于一个“已命中演员数组HitActors”中防止单次挥砍对同一目标多次造成伤害是则返回。检查Other Actor是否实现了特定的接口如BPI_Damageable或者是否属于某个特定的类如BP_Enemy。这是判断是否为可伤害对象的关键。4.2 应用伤害与触发接口确认命中有效目标后执行伤害逻辑。应用伤害使用“应用伤害Apply Damage”节点。“伤害承受者Damaged Actor”设为Other Actor。“基础伤害Base Damage”可以是一个固定值如30或是从角色属性中读取。“事件击中者Event Instigator”和“伤害制造者Damage Causer”通常都设为自身Self。“伤害类型类Damage Type Class”可以创建蓝图类继承自DamageType用于区分物理、魔法等伤害类型。这里可以传入None或一个基础伤害类型。触发视觉/逻辑反馈将Other Actor添加到HitActors数组中用于本次攻击的重复命中过滤。调用Other Actor上的自定义事件或接口函数例如OnHitReceived传递命中位置、攻击者等信息。这用于触发敌人的受击动画、音效等。生成命中特效使用“生成粒子系统Spawn Emitter at Location”节点。位置可以通过“组件重叠时”事件的Hit Result结构体中的Impact Point获取或者使用两个碰撞体位置的中间点。选择一个火花或冲击波粒子系统。显示伤害数字这通常通过一个UI组件实现。可以创建一个“控件组件Widget Component”附加到角色上或者使用“创建控件Create Widget”节点生成一个世界空间的UI。将伤害值传递给这个UI控件并显示。4.3 实现简单的受击反馈敌人端创建一个敌人蓝图BP_Enemy。在其事件图表中重载“任何伤害Event AnyDamage”事件。这个事件会在Apply Damage被调用时触发。在此事件中你可以减少生命值Health变量。播放一个受击动画蒙太奇Play Montage。触发一个受击音效。如果生命值0播放死亡动画并销毁或禁用角色。为了更精细的控制可以实现一个接口如BPI_Damageable里面定义一个函数ReceiveHit。这样攻击者角色可以直接调用接口函数而不必依赖Apply Damage事件。Apply Damage更适合处理纯粹的血量计算和游戏框架的死亡处理。5. 增强伤害反馈手感打磨基础的命中逻辑已经完成但要让战斗“有手感”还需要以下增强反馈。5.1 命中停顿Hit Pause命中瞬间的短暂时间停滞能极大地增强打击感。在攻击者角色命中目标时使用“设置全局时间膨胀Set Global Time Dilation”节点。将“时间膨胀Time Dilation”设置为一个很小的值例如0.01近乎暂停。设置一个极短的延迟例如0.05秒。延迟结束后再将“时间膨胀”设置回1.0。注意全局时间膨胀会影响整个游戏世界包括UI动画。对于多人游戏或需要更精细控制的情况应考虑使用自定义的时间膨胀系统或只暂停攻击者/受击者的动画。5.2 镜头震动Camera Shake在命中时为玩家控制的摄像机添加震动。首先需要创建一个镜头震动资产。在内容浏览器中右键“创建高级资源Create Advanced Asset” - “镜头震动Camera Shake”。在攻击者角色命中目标后使用“播放镜头震动Play Camera Shake”节点。选择你创建的镜头震动类并设置适当的强度和播放空间。5.3 攻击者动画速率微调为了让攻击动画在命中时更有“击中”的质感可以在命中瞬间短暂提高攻击动画的播放速率然后再恢复。在攻击者播放攻击蒙太奇时获取对蒙太奇实例的引用。命中时使用“设置播放速率Set Play Rate”节点将速率短暂提高到1.2左右。设置一个非常短的延迟如0.1秒后将速率设回1.0。6. 常见问题排查与优化实践即使按照步骤实现也可能会遇到各种问题。以下是一些常见坑点及其解决方案。6.1 连击不流畅或无法触发下一段问题现象可能原因检查与解决方案快速点击攻击键只能打出第一段bComboPressed变量未被正确缓存或检查确保在攻击输入事件中当bIsAttacking为真时能成功设置bComboPressed为真。在ComboWindowOpen事件中检查此变量后立即将其重置为假。连击窗口期感觉太短或太长动画通知Notify_ComboWindowOpen放置的位置不对回到蒙太奇中将连击窗口通知放在一段攻击动画的末尾几帧但要在下一段攻击开始之前。需要通过实际游玩测试来微调。有时能连有时不能状态变量bIsAttacking,bCanCombo在动画结束时没有正确重置在蒙太奇的最后一帧或通过单独的“攻击结束”通知确保将所有攻击相关状态变量重置为初始值。6.2 命中检测不可靠问题现象可能原因检查与解决方案武器穿模但未触发命中碰撞体大小、位置或旋转不正确在角色动画运行时通过“ 键在编辑器播放时显示碰撞体观察其是否与武器模型同步移动并覆盖有效区域。调整其附着骨骼和变换值。一次挥砍对同一目标造成多次伤害未在单次攻击内对已命中目标进行过滤在攻击开始时或激活碰撞体时清空一个“已命中数组”。在重叠事件中将目标加入数组并检查后续重叠。在攻击结束时或关闭碰撞体时清空数组。命中自己或队友碰撞过滤设置不当检查HitCollisionBox的碰撞预设和响应。确保它只与敌人如特定碰撞频道或对象类型发生重叠。可以在重叠事件中增加团队ID判断。6.3 性能与扩展性考虑碰撞体优化对于复杂的连续攻击可以考虑使用多个不同形状和激活时间的碰撞体来模拟挥砍轨迹而不是一个大盒子。伤害计算与属性系统将基础伤害值、连击倍率、暴击率等从硬编码改为从角色的“属性组件Attribute Component”或数据表中读取便于平衡和扩展。反馈系统抽象化将命中停顿、镜头震动、音效播放、特效生成等反馈逻辑封装成一个单独的“反馈管理器Feedback Manager”组件或函数库。这样不同的攻击技能可以配置不同的反馈强度或资源。网络同步多人游戏上述实现是单机版的。在多人游戏中几乎所有逻辑输入、状态、碰撞检测、伤害应用、反馈都需要在服务器端权威执行并通过属性复制Replication和远程过程调用RPC同步到客户端。这是一个复杂得多的主题需要系统设计网络角色和RPC。7. 从原型到生产最佳实践与扩展方向一个可玩的战斗原型已经构建完成但要将其用于实际项目还需要遵循一些工程实践。7.1 代码结构与数据驱动使用C父类与蓝图子类将核心战斗逻辑如连击状态管理、伤害计算框架写在C的ACombatCharacter类中。将具体的动画蒙太奇引用、特效、音效等资源配置在蓝图子类里。这样既保证了性能和控制力又保留了设计灵活性。数据资产Data Asset不要将连击段数、伤害值、窗口期时长等数值硬编码。创建UDataAsset派生类如UComboAttackData来存储这些数据。攻击技能、角色属性都可以通过数据资产配置方便策划调整。游戏技能系统Gameplay Ability System, GAS对于大型项目强烈建议学习并集成GAS。它是一个专门为复杂角色技能、属性和效果管理的UE插件提供了网络同步、预测、冷却、消耗等开箱即用的解决方案能极大地规范战斗系统的架构。7.2 反馈资源的制作与管理特效与音效命中特效火花、刀光、血雾和音效挥砍声、命中声、受击声需要美术和音频资源的支持。确保粒子系统不会过度消耗性能音效有合理的衰减和空间化设置。伤害数字UI创建一个UMG控件包含一个文本块。使用“动画Animation”轨道为其添加缩放、上浮、渐隐等关键帧动画。在生成时将伤害值设置为文本并播放动画。受击动画混合敌人的受击动画应该能很好地从任何当前动画混合过去。在动画蓝图中使用“插槽Slot”来播放蒙太奇并设置适当的混合时间。7.3 调试与测试清单在将战斗系统提交测试前自行完成以下检查功能正确性连击是否按预期工作每一段攻击的碰撞体激活范围是否准确伤害计算是否正确所有反馈特效、音效、屏幕震动是否触发边界情况在墙角攻击、攻击移动中的敌人、同时攻击多个敌人时系统表现是否正常攻击动画被打断时状态是否被正确重置性能表现在编辑器统计信息中检查激活多个敌人并进行战斗时的游戏线程、渲染线程和GPU性能。特别注意粒子特效和物理碰撞的开销。手感调优这是主观但至关重要的。邀请其他人试玩收集对攻击节奏、命中停顿时长、镜头震动强度、音效音量等方面的反馈并进行微调。通过将战斗系统分解为状态管理、碰撞检测、伤害反馈这几个相对独立的模块并逐一实现和调试你可以在UE5中构建出从简单到复杂、手感各异的战斗体验。记住核心在于精确的时机控制和即时的多感官反馈不断迭代和测试是打磨手感的不二法门。
返回列表