UE5攻击蓝图全解析:BP_SystemAttack近战平A实战

UE5攻击蓝图全解析:BP_SystemAttack近战平A实战 先和大家打个招呼。一次实战项目中我在 UE5 里实现角色的近战普通攻击时先是直接往角色蓝图里堆节点结果连招手感、伤害判定、动画触发全部挤在一起改一个需求就要在几百个节点里翻找。后续把攻击逻辑抽离到独立的BP_SystemAttack蓝图后状态清晰了调试也方便了不少。这篇文章就围绕这个攻击系统蓝图结合课程中近战平A这一集的内容完整拆解 UE5 攻击蓝图的编写思路、节点逻辑和常见坑点。这篇文章适合刚学 UE5 蓝图、想让角色打出近战平A的开发者。学完后你可以独立完成一次“输入触发 → 蒙太奇播放 → 动画通知 → 碰撞检测 → 伤害输出 → 特效反馈”的攻击链路并且知道如何扩展为三连击、重击或者技能系统。1. 近战攻击系统的作用与设计思路1.1 什么是 BP_SystemAttackBP_SystemAttack从命名上可以拆成两部分System表示这是一个系统级蓝图Attack表示它承载的是攻击逻辑。通俗地讲它可以是一个 Actor、一个 ActorComponent也可以是一个挂在角色身上的普通蓝图。它负责管理角色“攻击”这个行为的所有数据与流程。没有攻击系统蓝图时很多初学者会把攻击逻辑直接写在角色蓝图BP_Character中。这样做在只有一个角色、一个攻击动作时没问题但一旦出现多个角色共享攻击逻辑或者攻击动作需要频繁改动角色蓝图就会变得臃肿。比如角色蓝图既要管移动、跳跃、摄像机又要管出生、受伤、死亡再把攻击责任全部塞进去蓝图图表会很难维护。抽出BP_SystemAttack的目的就是让攻击逻辑单独存在。它只关心“能不能攻击”、“攻击哪一段”、“打到了谁”、“造成了多少伤害”画面表现仍由角色动画负责命中的特效和音效则交给 Niagara 与音频组件。这种“逻辑与表现分离”的设计在常见的中大型 UE5 项目中几乎都是标配。1.2 近战平A的完整流程一次近战平A从玩家按下按键到敌人掉血完整链路可以拆成 6 个阶段输入阶段玩家按下鼠标左键或手柄按键输入系统把事件发送给角色蓝图。状态判断攻击系统检查角色当前是否允许攻击。比如角色正在攻击、正在翻滚、正在死亡就不能再次触发攻击。动作播放角色播放攻击蒙太奇AnimMontage通常在这时锁定角色的移动或转向。判定窗口攻击动画播放到中间的某一帧时动画通知AnimNotify触发攻击判定事件攻击系统开始检测攻击范围。命中处理检测到攻击范围内有可伤害目标后调用目标的受伤接口计算伤害值触发Niagara命中特效和音效。状态复位动画播放完毕攻击状态重置角色可以再次进行下一次攻击。在这个流程中阶段 2 和阶段 4 是最容易出问题的。状态判断没做好角色会被攻击指令“打断”到一半的动画判定窗口没做对会出现“动画已经打到人了但实际没有伤害”或者“动画还没碰到人伤害已经打出去了”。1.3 为什么用蓝图而不是CUE5 中实现攻击逻辑可以用 C也可以用蓝图。两者的选择取决于项目定位和团队结构。对于初学者、独立开发者或者以原型验证为目的的项目蓝图有很明显的优势写节点比写代码直观变量和事件都能可视化调试时可以直接在节点上打断点查看数据流向。而且攻击逻辑本身并不复杂蓝图性能开销在普通规模项目中完全可接受。对于需要大量网络同步、需要高性能计算、或者需要多人协作的大型项目C 会更合适。BP_SystemAttack这种系统蓝图更多作为“数据容器”和“流程编排器”存在逻辑中消耗性能的部分再放到 C 函数中完成。本文以蓝图为主课程中的示例也是基于蓝图的适合入门阶段理解攻击系统原理。2. 环境准备与项目结构2.1 UE5 版本与基础配置本文示例使用的是 UE5 常见的标准第三人称模板版本上以 5.x 为例。需要特别说明的是不同 UE5 小版本在蓝图节点名称、动画资产细节、Niagara 创建入口等方面会有细微差异。你在自己的项目中如果发现个别节点名称不同可以先查看当前 UE5 版本对应的蓝图节点手册或者直接在蓝图搜索框中输入中文/英文关键词找到功能最接近的节点。在创建项目时建议选择“游戏”类别中的“第三人称”模板这样角色蓝图、基础动画蓝图、输入配置都已经具备可以专注于攻击系统的开发。项目名称可以命名为UE5AttackDemo目标平台使用“桌面平台”即可。2.2 角色与动画资产准备实现近战攻击前至少需要以下资产一个角色模型SKM_Character、Mesh。角色蓝图BP_Character。动画蓝图ABP_Character。攻击蒙太奇AM_Attack。攻击时的碰撞检测数据。如果暂时没有自己的角色模型可以直接使用 UE5 第三人称模板自带的SK_Mannequin模型。课程演示中也通常以引擎自带资产为主重点在逻辑编写。攻击蒙太奇需要从动画资产创建。在内容浏览器中选中一个攻击动作动画右键选择“创建” → “创建 AnimMontage”。创建后双击打开把动画片段拖拽到时间轴中。这里要注意动画片段在时间轴上出现的帧位置就是后续添加 AnimNotify 的位置。2.3 创建 BP_SystemAttack 蓝图在内容浏览器中调用“蓝图类” → “Actor”来创建攻击系统蓝图。注意这里选择 Actor 还是 ActorComponent取决于你想把攻击系统当成独立个体还是在角色身上挂载的组件。课程中的BP_SystemAttack使用的是 Actor 方式把它作为攻击系统的逻辑载体。如果你更习惯组件化开发也可以选择ActorComponent。两种方式节点本质相同只是挂载方式不同。创建完成后命名为BP_SystemAttack并添加一个Billboard组件方便在场景中辨认它的位置。2.4 输入映射设置在 UE5 中打开“项目设置” → “输入”默认已经存在IA_Attack或Attack输入操作。如果没有就新建一个输入操作名称类型按键IA_Attack数字布尔Digital Bool鼠标左键IA_Combo数字布尔Digital Bool鼠标左键连点在角色蓝图中把IA_Attack绑定到攻击事件的调用入口。绑定方式有两种一是使用EnhancedInput的InputAction节点二是使用旧的InputAxis或InputAction事件。UE5 默认推荐EnhancedInput本文示例以该方式展开。// 输入映射思路 输入动作 IA_Attack → 事件 IA_Attack角色蓝图 Event Graph → 调用 BP_SystemAttack 的 StartAttack 自定义事件3. 攻击状态机设计3.1 攻击状态变量定义在设计BP_SystemAttack之前首先要明确攻击过程需要哪些状态变量。这些变量会贯穿整个攻击逻辑。在BP_SystemAttack中创建以下变量变量名类型默认值说明CanAttackBooleantrue当前是否可以攻击IsAttackingBooleanfalse是否正在攻击中ComboCountInteger0当前连击段数MaxComboInteger3最大连击段数AttackMontageAnimMontage无攻击蒙太奇资产AttackRadiusFloat150.0攻击检测半径AttackDamageFloat30.0攻击伤害值这些变量在后续节点中会频繁使用。CanAttack与IsAttacking的区别需要理解清楚CanAttack表示角色处于“允许发起攻击”的状态比如角色还在走路、待机时值为 trueIsAttacking表示角色已经进入攻击动作例如攻击动画还在播放。实际判断时是两个条件同时检查。3.2 状态切换与互斥逻辑攻击逻辑中一个关键点是“互斥”角色在攻击动作期间不能重复触发攻击否则会出现动画闪断、伤害多次触发。在BP_SystemAttack中使用分支Branch节点判断StartAttack 自定义事件 ├── [分支] 判断 CanAttack 是否为 true │ ├── false → 直接返回不做任何处理 │ └── true → 继续执行 ├── [设置] CanAttack false ├── [设置] IsAttacking true ├── [播放] AttackMontage └── [延迟] 等待动画结束后调用 EndAttack这里有一个常见误区只用IsAttacking判断不使用CanAttack。这样会导致攻击结束后攻击状态变量仍然停留在某个旧值下一次攻击无法触发。一个简单的经验是CanAttack负责“入口开关”IsAttacking负责“执行过程标志”两者职责分明。3.3 连击窗口Combo Window近战平A如果只有一次攻击会显得很单薄。课程中演示了最基础的三连击设计核心思路是攻击动画播放到一定位置时开启“连击窗口”在这个窗口内玩家再次按下攻击键会触发下一段攻击如果超出窗口攻击结束。合理设计连击变量ComboCount从 0 开始。触发第一段时ComboCount 1。动画通知Notify_ComboWindowStart将CanCombo true。玩家再次攻击时检查CanCombo如果为 true则ComboCount并切换到第二段蒙太奇。动画通知Notify_ComboWindowEnd将CanCombo false。如果ComboCount达到最大值暂停接收连击输入。连击窗口的时间范围要与动画节奏匹配。窗口开启太早玩家连续按键会跳过前摇动画窗口开启太晚按键后需要反应时间连击手感会变得“不跟手”。一般以攻击动画中“动作已经发生明显变化”的位置作为窗口起点比如武器挥出到最高速度的那一帧。4. 核心攻击检测逻辑4.1 两个关键检测时机AnimNotify 与 AnimNotifyState在攻击动画播放过程中攻击系统需要知道“什么时候开始检测、什么时候结束检测”。这个“时机”不能靠纯粹的定时器猜测而是应该在动画时间轴上明确标记。UE5 提供两类节点类型名称作用AnimNotify动画通知AttackStart播放到该帧时触发一次事件开始检测AnimNotify动画通知AttackEnd播放到该帧时触发一次事件结束检测AnimNotifyState动画通知状态AttackCheck在指定时间段内持续触发可在其中做多帧判定使用AnimNotifyState的优势在于它可以绑定一段区间蓝图中可以区分“区间开始、区间结束、区间刷新”三个时机。课程中通常使用两个独立的AnimNotify从时间轴上标记攻击的“前摇结束”和“后摇开始”。在攻击蒙太奇中找到动画片段中武器挥动到目标方向的那一帧右键添加通知命名为AttackHitNotify。后续在BP_SystemAttack中通过Bind AnimNotify或直接使用AnimNotify事件绑定来触发检测逻辑。4.2 球形碰撞检测方案攻击判定最常用的方式是球形碰撞检测以角色前方某个位置为圆心以AttackRadius为半径检测范围内所有带碰撞的 Actor。在BP_SystemAttack中使用SphereOverlapActors节点核心参数如下参数设置值说明Spheres CenterSocket 或 Vector通常放在武器骨骼插槽位置或角色前方偏移位置Sphere RadiusAttackRadius攻击检测半径Object TypesWorldDynamic, Pawn只检测需要的对象类型Class FilterCharacter 或 Actor过滤目标类型Ignore Actors角色自身避免攻击到自己节点输出Actors数组遍历数组对每个目标调用伤害接口。这种方案的优点是逻辑简单、调试容易。你可以用DrawDebugSphere节点在视口中可视化攻击范围直观看到检测半径是否合理。DrawDebugSphere仅用于开发调试正式发布时应移除。// 碰撞检测逻辑 AttackHitNotify 触发 → SphereOverlapActors 检测 → ForEachLoop 遍历结果 → [判断] 是否属于可伤害目标 → 是 → 调用目标的 ReceiveDamage 函数 → 否 → 忽略4.3 射线检测方案除了球形碰撞检测部分近战攻击也可以使用射线检测例如直线枪刺、远程剑气。射线检测方案在 UE5 中常用LineTraceByChannel或LineTraceForObjects。LineTraceByChannel从起点发射一条射线到终点返回第一个被击中的对象。它可以检测到墙面、敌人、障碍物。在近战攻击中可以把射线起点放在角色视线方向终点放在前方一定距离处当命中敌人时触发伤害。UE5 热词中常提到的“射线障碍检测”就是这个思路的扩展不仅检测第一个目标还要检测路径上是否有阻挡物。比如角色在一个箱子后面出刀射线先打中箱子就应该停止继续检测后方敌人。实现方式是在射线命中物体后判断命中对象是否为障碍物如果Hit.BlockingHit为 true就不再进行后续穿透。使用射线检测时需要注意射线检测只能检测到直线路径上的目标适合“突刺”、“射击”类攻击不适合“横扫”类近战。如果角色拿的是大剑或棍棒球形重叠检测会更符合直觉。4.4 伤害计算与命中反馈检测命中目标后BP_SystemAttack需要把伤害值传递出去。UE5 中常用两种方式第一种是直接调用目标蓝图上的自定义事件事件名比如ReceiveDamage传入参数为DamageValue、HitDirection、HitFromDirection等。这种方式直观但要求所有可伤害目标蓝图都有相同命名的自定义事件。第二种是使用 UE5 的GameplayStatics - ApplyDamage节点。该节点会向目标 Actor 发送TakeDamage事件是通用伤害接口。蓝图和 C 都支持适合后续扩展技能系统。推荐使用第二种方式因为它的兼容性更好。后续如果接入 GASGame Ability System或者把系统迁移到 C伤害通路不用重写。命中反馈包括播放命中音效。在命中点生成 Niagara 特效比如血液飞溅、火花、能量迸发。给目标一个屏幕 hitshake 或受击动画。Niagara 特效可以在角色蓝图或攻击系统蓝图中通过Spawn System at Location节点生成位置取Hit.ImpactPoint。如果命中目标是可破坏物或 NPC还可以在目标身上调用PlayHitReact之类的动画事件。5. 完整蓝图串联与运行验证5.1 BP_SystemAttack 事件逻辑在实际编写时BP_SystemAttack的 Event Graph 节点并没有想象中复杂。下面用一个文本形式的伪代码说明完整的节点连接逻辑事件 BeginPlayBP_SystemAttack ├── [设置] OwnerCharacter 方案生成的拥有者角色 自定义事件 StartAttack ├── [分支] CanAttack true │ ├── false → Return │ └── true │ ├── [设置] CanAttack false │ ├── [设置] IsAttacking true │ ├── [设置] ComboCount 1 │ ├── [播放蒙太奇] AM_Attack_1 │ └── [设置定时器] ResetAttackState, 延迟 0.5 秒 自定义事件 ComboAttack ├── [分支] IsAttacking true 且 CanCombo true │ ├── false → Return │ └── true │ ├── [设置] CanCombo false │ ├── [增量] ComboCount │ ├── [切换蒙太奇] 根据 ComboCount 播放 AM_Attack_2 / AM_Attack_3 │ └── 再次设置定时器 自定义事件 EndAttack ├── [设置] IsAttacking false ├── [设置] CanAttack true ├── [设置] ComboCount 0 └── [通知] 动画蓝图恢复移动状态 事件 AttackHitNotify动画通知绑定 ├── [执行] SphereOverlapActors ├── [循环] 遍历 OverlapActors │ ├── [判断] Actor 是否可伤害 │ │ → 是 → ApplyDamage Niagara 特效 │ └── [结束循环]这个流程中ResetAttackState定时器可以用Set Timer by Event节点实现。定时器时间不宜过短否则连击窗口无法形成也不宜太长否则攻击结束后角色会有一小段“卡住”体感。课程中一般建议在动画后摇开始时重置状态。5.2 角色蓝图中调用攻击系统在角色蓝图BP_Character中需要把输入事件连接到攻击系统。首先在角色蓝图中放置一个BP_SystemAttack类型的变量命名为SystemAttackRef。然后在BeginPlay中Spawn Actor这个蓝图类并设置它的拥有者为当前角色。在 Event Graph 中添加IA_Attack输入事件事件 IA_Attack按下 ├── [分支] SystemAttackRef 是否有效 │ ├── false → 创建并生成 SystemAttackRef │ └── true │ └── [调用] SystemAttackRef - StartAttack 事件 IA_Combo按下 ├── [分支] SystemAttackRef 是否有效 │ ├── false → Return │ └── true │ └── [调用] SystemAttackRef - ComboAttack这里出现一个细节攻击系统蓝图里的事件如何被角色调用两种方式都可行将角色蓝图中的自定义事件设置为Public访问级别。或在BP_SystemAttack中把自定义事件设为“可调用”。建议在BP_SystemAttack中创建自定义事件时把Input相关参数保留出来方便外部传参。比如StartAttack中传入AttackDirection、AttackType等参数这样后续扩展技能攻击时不需要修改入口。5.3 动画通知相关设置在攻击蒙太奇AM_Attack_1中需要把动画通知与BP_SystemAttack连接起来。动画通知本身不会自动调用任意蓝图事件需要做一次“绑定”。常见做法是在角色动画蓝图ABP_Character中处理AnimNotify事件再把事件转发给BP_SystemAttack。也可以在攻击系统蓝图中使用Bind AnimNotify的方式不过后者对初学者来说更绕。具体操作步骤打开攻击蒙太奇将动画片段拖入时间轴。在时间轴上右键添加通知AttackHitNotify。打开动画蓝图找到该通知的事件节点。在事件节点中获取攻击系统引用调用AttackHit或PerformHitDetection自定义事件。这样动画播放到指定帧时通知会被动画蓝图捕获再转发给攻击系统执行检测逻辑。如果动画蓝图中没有该通知的事件节点通常是因为通知名称拼写不一致或者动画蓝图的类不是该动画使用的类。5.4 运行验证完成上述设置后按PIE运行游戏。测试清单如下验证项目预期结果按下鼠标左键角色播放第一段攻击动画动画中再次按下左键连击窗口开放时触发第二段攻击动画未结束强制按键不会打断当前动画攻击范围内有敌人敌人掉血生成命中特效攻击范围外攻击不产生任何伤害判定攻击结束后立即攻击可正常触发第一段攻击调试时可以在攻击判定处增加打印节点输出被命中目标的名称。如果打印为空先检查碰撞检测半径、对象类型和Ignore Actors的设置。6. 常见问题与排查思路蓝图攻击系统写完后最容易遇到以下几类问题。我根据不同现象整理了排查思路问题现象常见原因解决思路按下攻击键没有任何反应输入动作没有绑定或攻击系统引用为空检查输入映射、BeginPlay中是否成功生成BP_SystemAttack攻击动画播放了但没有伤害动画通知没有触发或检测范围设得太小在动画时间轴中确认AttackHitNotify位置开启DrawDebugSphere查看检测范围攻击动画被连续按键打断状态判断不完整检查CanAttack与IsAttacking分支逻辑攻击中应阻止再次触发连击只能打出第一段ComboCount没有在动画结束后重置在连击窗口结束后重置ComboCount或在EndAttack中归零攻击检测到了自己没有在SphereOverlapActors中忽略自身在Ignore Actors数组中加入当前角色动画播放结束后一段时间内无法再次攻击定时器时长设置太长缩短ResetAttackState延迟或在动画结束后立即调用EndAttackNiagara 特效没有生成特效资产未加载或生成位置错误确认Spawn System at Location的模板资产已添加位置改为命中点网络联机时伤害不同步未使用Execute Server/Multicast使用 Server 确认逻辑与 Multicast 广播伤害事件其中最常见的是“动画播放了但没有伤害”。排查顺序为先看动画通知有没有触发再看检测半径是否覆盖目标最后确认目标是否被过滤。使用Print String在AttackHitNotify事件中打印一行字符如果字符没有输出说明动画通知绑定没有走通优先处理通知相关设置。另一个容易被忽略的问题是“攻击过程中角色可以移动”。如果攻击动画播放中允许移动会造成攻击判定范围与表现不匹配。常规做法是在StartAttack中设置角色MovementMode为None在EndAttack中恢复为Walking或者使用角色移动组件的MaxWalkSpeed临时降为 0。7. 最佳实践与工程建议7.1 状态变量的命名与脚本规范蓝图变量命名建议统一加前缀布尔类型变量用b开头比如bCanAttack、bIsAttacking对象引用用Ref结尾比如OwnerCharacterRef。虽然蓝图不强制类型前缀但规范命名在项目变大后能显著降低理解成本。攻击蓝图内的自定义事件也可以按照“动作 时机”命名例如StartAttack、ComboAttack、EndAttack、PerformHitDetection。不要用Event_1、Func_2这类无意义名称。7.2 参数配置不要写死在节点里攻击半径、伤害值、蒙太奇资源等参数尽量作为变量暴露在BP_SystemAttack的 Details 面板中。这样后续调整攻击手感时可以直接在蓝图实例上修改不需要重新排节点。可以勾选变量的“Instance Editable”和“Expose on Spawn”这样在Spawn Actor时就能直接传入不同参数。比如不同武器可以在生成攻击系统时传入不同的攻击半径和蒙太奇。7.3 攻击检测建议放在 Server 端如果项目是联机游戏攻击检测不能只在客户端执行。否则每个玩家的伤害结果不一致甚至会出现“我这边打中了对方没掉血”的情况。实现思路是使用Has Authority分支判断服务器权限。在服务器端执行碰撞检测和伤害计算然后通过Multicast或RPC通知所有客户端播放特效和音效。客户端的表现只做视觉反馈不做逻辑判定。单机开发阶段可以暂时忽略这一层但如果提前加上服务器判断后期接入联机时会省很多事。7.4 Niagara 特效与攻击节奏的配合Niagara 系统在攻击中的常见用法是两类一类是攻击挥动时的拖尾特效另一类是命中时的迸发特效。拖尾特效可以挂在武器的骨骼插槽上使用 Niagara 的Skeletal Mesh Location更新器跟随武器移动命中特效则在AttackHitNotify触发位置生成。特效细节要注意命中特效经常出现“没打到人但特效就爆了”的错觉原因是生成点不在真实命中点。在碰撞检测返回中优先使用Hit.ImpactPoint或者Out Hit Result.ImpactPoint作为特效生成位置而不是直接使用角色位置。7.5 攻击帧与动画事件的一致性攻击检测的触发帧必须与动画表现一致。一个常见的节奏错误是动画中的武器在攻击动作第 10 帧就挥到了敌人面前但通知设置在第 20 帧导致玩家感觉“打到了却没有伤害反馈”。建议在动画资源中打开“预览网格体”逐帧查看武器到达目标的时间点。然后在时间轴上把攻击通知放置在那个时间点附近不要提前太多。通过反复试玩来微调这个偏移通常能得到比较舒服的打击手感。8. 总结与下一步学习方向这一集中我们完成了BP_SystemAttack蓝图的核心框架从输入绑定、状态变量、连击窗口、攻击蒙太奇到碰撞检测、伤害输出和 Niagara 命中特效。这套逻辑是后续技能系统、敌人受击反馈、AI 攻击判断的基础。在开始写自己的攻击系统时可以参考以下几个练习方向给BP_SystemAttack增加一个重击分支使用不同蒙太奇和更大伤害值。实现“受击队列”功能记录同一帧内被命中的所有目标避免重复伤害。尝试把攻击检测改为多段式检测例如每隔 0.05 秒检测一次适配更长的挥砍动画。使用动画通知状态AnimNotifyState替代两个独立 AnimNotify体验持续判定和一次判定的差别。给攻击系统增加耐力消耗角色没有耐力时无法攻击。近战攻击虽然是最基础的动作能力但它涉及了 UE5 中蓝图、动画、物理、Niagara 多个系统的配合。把这套逻辑梳理清楚后再做怪物 AI、Boss 连招、技能组合都会顺手很多。