这次我们来看一个 UE5.7 战斗系统开发实战项目,重点不是讲虚幻引擎有多强大,而是如何在 UE5.7 这个版本下,快速实现一套包含连击、命中判定和伤害反馈的实战系统。对于独立开发者或小团队来说,战斗系统的核心在于手感与反馈,而非复杂的底层架构。
这个项目源自一个双语(中英)实战教程,旨在解决 UE5 战斗开发中常见的几个痛点:连击逻辑如何平滑衔接、命中检测如何精准高效、伤害反馈如何让玩家“拳拳到肉”。我们将围绕这些核心功能,拆解从蓝图设计到 C++ 实现的完整流程。
本文将带你完成一套可运行的战斗系统原型搭建。你会看到如何设置动画状态机来处理连击,如何使用碰撞体或射线进行命中检测,以及如何通过 UI、音效、镜头抖动和受击动画来构建立体的伤害反馈。无论你是想为你的动作游戏注入灵魂,还是单纯学习 UE5.7 的新特性在游戏逻辑中的应用,这篇文章都能提供直接的代码和思路。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 开发引擎 | Unreal Engine 5.7 |
| 核心功能 | 连击系统、命中判定、多维度伤害反馈(视觉、听觉、触觉) |
| 实现方式 | 蓝图可视化脚本 + C++ 底层逻辑(可选) |
| 硬件门槛 | 满足 UE5.7 官方推荐配置即可,主要依赖 CPU 单核性能与内存 |
| 输出目标 | 可独立运行的战斗原型,支持打包到 Windows 等平台 |
| 适合场景 | 动作游戏、ARPG、格斗游戏的原型开发与核心战斗逻辑学习 |
2. 适用场景与使用边界
这套战斗系统实战方案主要面向以下几类开发者:
- 独立游戏开发者 :需要快速验证战斗玩法核心循环,搭建可演示的原型。
- UE5 学习者 :希望超越静态场景搭建,深入理解游戏逻辑、动画蓝图与物理交互的实战结合。
- 中小型团队 :作为技术预研,验证特定战斗手感(如硬直、连招)的可行性。
它能解决的问题包括:
- 连击手感生硬 :通过动画通知和状态机逻辑,实现按键输入缓冲、连招窗口判定,使连击流畅自然。
- 命中检测不准 :对比球形碰撞体、胶囊体碰撞与射线检测的优劣,实现精准的武器攻击范围判定。
- 反馈维度单一 :整合屏幕抖动、命中停顿(Hit Pause)、伤害数字、受击音效与动画,营造强烈的打击感。
需要注意的边界:
- 非网络同步方案 :本文重点在单机本地逻辑实现,如需多人对战,需自行扩展网络复制(Replication)和预测(Prediction)逻辑。
- 性能非极致优化 :方案以清晰易懂为首要目标,对于需要支持大量单位同时战斗的 RTS 或 MMO 场景,需对检测算法和反馈系统进行深度优化。
- 美术资源依赖 :良好的反馈需要高质量的动画、音效和 VFX 资源支持,本文提供逻辑框架,资源需自行准备或使用 Marketplace 资源。
3. 环境准备与前置条件
在开始编码之前,请确保你的开发环境已就绪。
- Unreal Engine 5.7 :这是核心。务必从 Epic Games Launcher 或 GitHub 源码编译安装 5.7.x 版本。不同小版本间 API 可能有细微差别。
- 项目模板 :建议使用 “第三人称游戏(C++)” 模板创建新项目。这会自动生成角色(Character)基础类、动画蓝图和输入设置,节省大量初始化时间。
-
硬件配置
:
- 操作系统 :Windows 10/11 64位。
- CPU :四核及以上,主频建议 3.0 GHz 以上。战斗逻辑和动画计算对单核性能敏感。
- 内存 :16GB 及以上。UE5 编辑器本身占用较大,建议 32GB 以获得流畅体验。
- 显卡 :支持 DirectX 12 的显卡。GTX 1060 / RTX 2060 或同等性能以上可满足开发需求,显存 6GB 以上更佳。
- 存储 :SSD 硬盘。项目文件和引擎加载速度会显著提升。
- 基础概念 :需要对 UE5 的蓝图(Blueprint)、动画蓝图(AnimBlueprint)、碰撞(Collision)通道、以及 C++ 与蓝图交互有基本了解。
4. 项目结构与核心类设计
一个清晰的项目结构能让开发事半功倍。我们建议按如下方式组织:
Content/
├── Characters/
│ ├── Hero/
│ │ ├── Animations/ # 放置角色动画(蒙太奇、混合空间)
│ │ ├── Blueprints/ # 角色蓝图、动画蓝图
│ │ └── Meshes/ # 角色骨骼网格体
│ └── Enemy/
├── Core/
│ └── Blueprints/ # 游戏模式、玩家控制器、游戏实例等
├── UI/ # 伤害数字、血条等 Widget
├── VFX/ # 命中火花、刀光等粒子效果
└── Sounds/ # 攻击、受击、环境音效
Source/YourProjectName/
├── YourProjectName.Build.cs
├── YourProjectName.h/.cpp
├── HeroCharacter.h/.cpp # 玩家角色C++类
├── EnemyCharacter.h/.cpp # 敌人角色C++类
├── CombatComponent.h/.cpp # 战斗逻辑组件(核心)
└── DamageType_Melee.h/.cpp # 自定义伤害类型
核心类说明:
-
AHeroCharacter:继承自ACharacter,负责移动、输入绑定和高级战斗指令转发。 -
UCombatComponent:一个UActorComponent。 这是战斗系统的中枢 ,所有连击状态、攻击检测、伤害计算逻辑都应集中于此,便于管理和复用。 -
AEnemyCharacter:敌人角色,包含生命值属性、受击反应接口。 -
UDamageType_Melee:自定义伤害类型,用于区分近战伤害与其他伤害,以便触发特定的反馈效果。
5. 连击系统实现:从输入到动画
连击系统的目标是让多次攻击动作能根据玩家输入节奏,平滑、可预测地衔接。
5.1 动画资源准备
- 准备至少 3-4 个连续攻击的动画序列(如 Attack01, Attack02, Attack03)。
- 在动画蓝图中创建 动画蒙太奇(Animation Montage) 。将攻击动画按顺序添加为蒙太奇片段(Section),并合理设置每个片段的开始和结束位置。
-
在动画序列的
关键帧
上添加
动画通知(Animation Notify)
。通常需要两种通知:
-
AnimNotify_AttackStart:在武器挥出的瞬间触发,用于开启命中检测。 -
AnimNotify_AttackEnd:在攻击动作收招时触发,用于关闭命中检测,并重置连击状态,允许输入下一击。
-
5.2 输入与状态逻辑(蓝图/C++)
在
UCombatComponent
中,我们需要管理几个关键状态变量:
// CombatComponent.h
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class YOURPROJECT_API UCombatComponent : public UActorComponent
{
GENERATED_BODY()
public:
// 绑定到角色的输入动作
UFUNCTION(BlueprintCallable, Category = "Combat")
void StartAttack();
// 内部状态
UPROPERTY(BlueprintReadOnly, Category = "Combat State")
bool bIsAttacking = false;
UPROPERTY(BlueprintReadOnly, Category = "Combat State")
int32 CurrentComboCount = 0;
UPROPERTY(EditDefaultsOnly, Category = "Combat")
float ComboWindowTime = 0.5f; // 连击有效输入窗口时间
private:
FTimerHandle ComboResetTimerHandle;
void ResetCombo();
void PerformAttackCheck();
};
// CombatComponent.cpp 简化逻辑
void UCombatComponent::StartAttack()
{
if (!bIsAttacking)
{
// 开始第一次攻击
bIsAttacking = true;
CurrentComboCount = 1;
PlayAttackMontage(CurrentComboCount);
// 设置定时器,超时后重置连击
GetWorld()->GetTimerManager().SetTimer(ComboResetTimerHandle, this, &UCombatComponent::ResetCombo, ComboWindowTime, false);
}
else if (bIsAttacking && CurrentComboCount < MaxComboCount)
{
// 在连击窗口内再次按下攻击键
// 可以设置一个 bComboInputReceived 标志,在 AnimNotify_AttackEnd 时检查并播放下一个连段
bComboInputReceived = true;
}
}
// 在动画通知 AttackEnd 时调用
void UCombatComponent::OnAttackEnd()
{
if (bComboInputReceived)
{
CurrentComboCount++;
PlayAttackMontage(CurrentComboCount);
bComboInputReceived = false;
// 重置连击窗口计时器
GetWorld()->GetTimerManager().ClearTimer(ComboResetTimerHandle);
GetWorld()->GetTimerManager().SetTimer(ComboResetTimerHandle, this, &UCombatComponent::ResetCombo, ComboWindowTime, false);
}
else
{
// 没有连击输入,结束攻击状态
bIsAttacking = false;
CurrentComboCount = 0;
}
}
5.3 动画蓝图(AnimGraph)连接
在角色的动画蓝图中,使用
状态机(State Machine)
来管理待机、移动和攻击状态。攻击状态应链接到播放
Attack Montage
的槽位(Slot),并根据
CurrentComboCount
变量跳转到蒙太奇中对应的片段(Section)。
6. 命中判定:精准检测的实现策略
命中判定是战斗真实感的基础。UE5 提供了多种方式,我们将分析其适用场景。
6.1 方案对比与选择
| 检测方式 | 实现复杂度 | 性能开销 | 精度 | 适用场景 |
|---|---|---|---|---|
| 球形/胶囊体碰撞 | 低 | 中 | 中 |
范围攻击、钝器挥砍、简单近战。通过
AnimNotify
触发碰撞体开启/关闭。
|
| 射线检测(Line Trace) | 中 | 低 | 高 | 刀剑劈砍、穿刺攻击。需要计算武器轨迹。 |
| 盒体检测(Box Trace) | 中 | 中 | 高 | 宽面武器挥砍(如巨剑)。精度和性能平衡较好。 |
| 物理模拟(Physics) | 高 | 高 | 高 | 需要真实物理交互,如击飞、布娃娃。 |
对于大多数近战连击, “动画通知+盒体检测” 是兼顾效果和效率的选择。
6.2 盒体检测(Box Trace)实战代码
在
UCombatComponent
中实现检测函数:
// CombatComponent.h
public:
UFUNCTION(BlueprintCallable, Category = "Combat|Detection")
void PerformWeaponTrace();
UPROPERTY(EditDefaultsOnly, Category = "Combat|Detection")
FVector TraceBoxHalfSize = FVector(30.0f, 10.0f, 10.0f); // 检测盒体大小
UPROPERTY(EditDefaultsOnly, Category = "Combat|Detection")
float TraceDistance = 100.0f; // 检测距离
// CombatComponent.cpp
void UCombatComponent::PerformWeaponTrace()
{
if (!GetOwner()) return;
ACharacter* OwnerCharacter = Cast<ACharacter>(GetOwner());
if (!OwnerCharacter) return;
// 1. 计算检测起始和结束位置(通常基于武器骨骼或角色前方)
FVector StartLocation = OwnerCharacter->GetActorLocation() + OwnerCharacter->GetActorForwardVector() * 50.0f;
FVector EndLocation = StartLocation + OwnerCharacter->GetActorForwardVector() * TraceDistance;
FRotator Orientation = OwnerCharacter->GetActorRotation();
// 2. 执行盒体检测
TArray<FHitResult> HitResults;
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(GetOwner()); // 忽略自身
bool bHit = GetWorld()->SweepMultiByChannel(
HitResults,
StartLocation,
EndLocation,
Orientation.Quaternion(),
ECC_Pawn, // 使用Pawn通道,或自定义“Weapon”通道
FCollisionShape::MakeBox(TraceBoxHalfSize),
QueryParams
);
// 3. 处理命中结果
if (bHit)
{
for (const FHitResult& Hit : HitResults)
{
AActor* HitActor = Hit.GetActor();
if (HitActor && HitActor != GetOwner())
{
// 应用伤害
UDamageType_Melee* MeleeDamageType = NewObject<UDamageType_Melee>();
UGameplayStatics::ApplyDamage(HitActor, 10.0f, OwnerCharacter->GetController(), GetOwner(), MeleeDamageType->StaticClass());
// 触发命中反馈(将在下一节实现)
OnHitConfirmed(Hit, HitActor);
}
}
}
// 【调试】在编辑器中显示检测盒体
#if WITH_EDITOR
DrawDebugBox(GetWorld(), (StartLocation + EndLocation) / 2, TraceBoxHalfSize, Orientation.Quaternion(), FColor::Red, false, 2.0f);
#endif
}
在
AnimNotify_AttackStart
通知中调用
PerformWeaponTrace()
。
7. 伤害反馈:营造“打击感”的立体工程
伤害反馈是让玩家感受到“击中”的关键。它需要多系统协同。
7.1 视觉反馈
-
伤害数字(UI) :
-
创建
Widget Component附加到受击角色。 -
使用
UMG设计一个简单的文本控件,显示伤害值。 - 在应用伤害时,在受击点附近生成此 Widget,并播放一个向上漂浮、渐隐的动画。
// 在敌人角色或全局函数中 void AEnemyCharacter::SpawnDamageNumber(float DamageAmount, FVector WorldLocation) { if (DamageNumberWidgetClass) { UUserWidget* DamageWidget = CreateWidget<UUserWidget>(GetWorld(), DamageNumberWidgetClass); if (DamageWidget) { // 设置Widget位置(可转换为屏幕空间) // 播放内置动画 } } } -
创建
-
命中特效(VFX) :
- 使用 Niagara 或 Cascade 创建刀光、火花、血液喷溅等粒子系统。
-
在
OnHitConfirmed函数中,根据命中位置和法线方向,使用UGameplayStatics::SpawnEmitterAtLocation生成特效。
-
屏幕抖动(Camera Shake) :
-
创建
CameraShakeBase子类,定义抖动强度、频率和时长。 -
命中后,在玩家控制器中调用
PlayerCameraManager->StartCameraShake()。
-
创建
-
命中停顿(Hit Pause) :
- 这是格斗游戏的核心技巧。命中瞬间短暂停止游戏时间。
// 设置全局时间膨胀 UGameplayStatics::SetGlobalTimeDilation(GetWorld(), 0.01f); // 近乎暂停 // 使用定时器在0.1秒后恢复 FTimerHandle PauseTimerHandle; GetWorld()->GetTimerManager().SetTimer(PauseTimerHandle, [](){ UGameplayStatics::SetGlobalTimeDilation(GetWorld(), 1.0f); }, 0.1f, false);
7.2 听觉反馈
-
受击音效
:根据命中材质(肉、金属、石头)播放不同的音效。使用
UGameplayStatics::PlaySoundAtLocation。 - 武器挥砍音效 :在攻击动画开始时播放。
- 环境音效 :如风声、角色吼叫,增强氛围。
7.3 物理与动画反馈
-
受击动画(Hit Reaction)
:
- 为敌人制作几个受击动画蒙太奇(前仰、后仰、踉跄)。
-
在敌人角色中实现
TakeDamage函数,根据伤害值和方向,播放对应的受击蒙太奇。
-
轻微位移
:命中时,让敌人或玩家角色产生一个微小的后退或击退效果,可以通过
LaunchCharacter或修改速度实现。
8. 集成测试与效果验证
现在,将所有部分组合起来进行测试。
8.1 测试流程
-
环境启动
:在 UE5.7 编辑器中打开项目,确保
HeroCharacter和EnemyCharacter已放置于关卡中。 -
输入绑定
:在项目设置中,将
Attack动作映射到鼠标左键或手柄按键,并绑定到HeroCharacter的StartAttack函数。 -
基础连击测试
:
- 运行游戏,控制角色靠近敌人。
- 连续按下攻击键,观察动画是否按顺序流畅播放(Attack01 -> Attack02 -> Attack03)。
- 验证点 :连击窗口内按键是否能成功触发下一段;窗口外按键是否会重置连击。
-
命中判定测试
:
-
攻击时,打开控制台命令
ShowDebugTraces或通过代码中的DrawDebugBox可视化检测盒体。 - 观察盒体是否在正确的动画帧出现,并覆盖武器运动轨迹。
- 攻击命中敌人时,查看日志是否输出命中信息,敌人生命值是否减少。
-
攻击时,打开控制台命令
-
伤害反馈综合测试
:
- 视觉 :确认伤害数字弹出、命中特效生成、屏幕轻微抖动。
- 听觉 :确认攻击音效和受击音效正确播放。
- 动画 :确认敌人播放受击动画,并有轻微的击退效果。
-
手感
:整体感受“打击感”是否扎实。调整
Hit Pause时长、屏幕抖动强度、音效音量以达到最佳效果。
8.2 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 连击动画不衔接,直接复位 |
连击输入窗口太短;
AnimNotify_AttackEnd
调用过早
|
1. 打印
bComboInputReceived
变量状态。
2. 延长
ComboWindowTime
。
| 调整连击窗口时间;确保连击输入标志在动画可取消帧之后才被重置。 |
| 攻击打不到敌人 | 检测盒体位置/大小不对;碰撞通道未设置 |
1. 启用
DrawDebugBox
可视化盒体。
2. 检查
ECC_Pawn
通道是否被双方骨骼网格体阻挡。
| 根据武器骨骼Socket位置计算检测起点;调整盒体大小;确保敌人碰撞体正确响应检测通道。 |
| 命中后无任何反馈 |
ApplyDamage
未调用或敌人未实现
TakeDamage
;反馈系统未触发
|
1. 在
PerformWeaponTrace
和敌人
TakeDamage
中打断点或打印日志。
2. 检查伤害类型和反馈蓝图事件是否绑定。 |
确保伤害应用流程贯通;在敌人蓝图中实现
AnyDamage
事件并触发反馈逻辑。
|
| 屏幕抖动影响所有物体 | Camera Shake 强度或范围过大 |
调整 Camera Shake 资产中的
Oscillation Duration
和
Rotational Amplitude
。
| 创建专用的、强度适中的近战命中 Camera Shake。 |
| 打包后特效/音效缺失 | 资源未正确打包 |
检查
Project Settings -> Packaging
中的资源列表。
|
确保使用的 VFX、音效资源在
Additional Asset Directories to Cook
中,或其所在目录已被包含。
|
9. 性能优化与扩展建议
当基础系统运行稳定后,可以考虑以下优化和扩展方向。
9.1 性能优化
-
检测优化
:
-
按需检测
:仅在
AnimNotify_AttackStart和AnimNotify_AttackEnd之间执行检测,避免每帧计算。 -
简化形状
:在保证效果的前提下,使用
SphereTrace代替BoxTrace。 - 对象池 :对频繁生成的伤害数字、命中特效使用对象池管理,避免频繁创建销毁。
-
按需检测
:仅在
-
动画优化
:
- 使用 动画压缩 减少内存占用。
- 对于非主角的敌人,可以考虑使用 较低精度的 LOD(细节层次)动画 。
-
反馈优化
:
- 将屏幕抖动、音效播放等操作放在客户端执行,减少网络复制开销(对于多人游戏)。
9.2 系统扩展
-
技能系统
:在
UCombatComponent基础上,扩展Skill数据结构,管理冷却时间、资源消耗和更复杂的检测逻辑(如扇形区域攻击、抛物线投射物)。 -
状态系统(Buff/Debuff)
:实现一个
UStateComponent,管理燃烧、中毒、眩晕等状态,并影响角色的属性(生命值、速度、攻击力)和战斗行为。 -
更复杂的连招
:引入“轻攻击”、“重攻击”组合,实现“轻-轻-重”等派生连招。可以通过一个
ComboTree数据结构来管理连招树。 - 锁定系统 :实现角色锁定功能,使攻击和检测方向自动朝向锁定目标,提升 3D 动作游戏的体验。
10. 总结与下一步
这套基于 UE5.7 的战斗系统实战方案,从连击、命中到反馈,覆盖了动作游戏核心手感的实现链条。它的价值在于提供了一个 清晰、可运行、可调试 的原型框架,让你能快速验证想法,并在此基础上进行深度定制。
最值得你优先尝试的,是
连击输入窗口
和
命中盒体调试
。这两个环节直接决定了操作是否跟手、打击是否扎实。通过调整
ComboWindowTime
和可视化
DrawDebugBox
,你能立刻感受到手感的变化。
最容易踩的坑是 动画通知时序 和 碰撞通道设置 。务必确保你的检测逻辑在正确的动画帧被激活,并且你的攻击检测通道与敌人的碰撞预设(Collision Preset)正确匹配。
下一步,你可以将
UCombatComponent
进一步抽象,把攻击数据(伤害值、检测形状、特效)配置到
DataTable
或
DataAsset
中,实现数据驱动。这样,策划人员无需修改代码,就能调整平衡性和技能效果。
2856



被折叠的 条评论
为什么被折叠?



