2.5 受击-死亡-复活链路:GA 生命周期的串联实战
核心结论
把前四篇的零件接成一条完整链路:受击判定 -> 属性变化 -> 死亡判定 -> 死亡表现 -> 复活。这条链路是 GAS 价值最好的演示——全程没有"直接改血量"的代码,每个环节都由系统自动接力。
链路全图
[攻击判定](AnimNotify 触发)
|
v
[服务器:Apply GE_Damage]
|
v
[AttributeSet: Health 变化]
|
v
[事件 OnHealthChanged 广播]
|----> 飘字 UI(伤害数字)
|----> 受击 GA(受击动画 + 音效)
|----> 血条 UI
|
v
[Health <= 0?] -- 是 --> [死亡 GA:Die]
| +-- 移动模式 Flying(防掉落)
| +-- 隐藏碰撞/UI
| +-- 播死亡 Montage
| +-- 计时器 -> 复活流程
否
v
[继续战斗]
关键点: - 伤害是数据流,不是函数调用:GE -> 属性变化 -> 事件。UI/特效/任务各自订阅,互不干扰。 - 死亡判定在服务器:所有玩家看到同一份死亡真相。 - 复活是"死亡 GA 的延续":一个 GA 走完整个生命周期。
死亡 GA 的实现要点
| 要点 | 做法 |
|---|---|
| 禁止移动 | CMC 切 Flying/设置 Speed=0 |
| 防止物理交互 | 碰撞关掉或切 Ragdoll |
| 停止其他技能 | CancelAbilities(带 Tag 筛选) |
| 死亡表现 | Montage 或 Ragdoll(看美术风格) |
| 计时复活 | GA 内 SetTimer 或延迟节点(服务器计时) |
注意:不要用 DestroyActor 删除玩家角色——玩家 Controller 与 ViewTarget 还绑定着。用"死亡表现 + 冻结",复活时还原。
复活的三段式
- 复活准备:透明/无敌 2 秒(防 spawn kill),镜头从观战拉回。
- 复活演出:站起 Montage,碰撞恢复。
- 恢复战斗:Heal GE 回满血,
EndAbility结束死亡 GA。
常见坑与解法
坑 1:客户端血量不同步
原因:属性的 RepNotify 没配。
解法:AttributeSet 的 Health 设 ReplicatedUsing=OnRep_Health,客户端变化时也触发 UI 更新(飘字只在服务器与命中者两端播)。
坑 2:死亡时角色还在受击
原因:其他 GA 没被取消。
解法:死亡 GA 第一件事 CancelAllAbilities(或按 Tag),并把"受击"状态写入 Tag,受击 GA 的 Trigger 检查。
坑 3:复活后属性不对
原因:复活时直接 Set 血量,跳过了 GE 通道。
解法:复活也用一个 GE(Heal),与 buff/伤害走完全相同的通道。通道纪律是全链路一致的。
坑 4:联机时模拟代理的死亡不同步
解法:死亡状态用 Gameplay Tag 同步(State.Dead),动画蓝图与 UI 都读这个 Tag(而非判断血量)。
相关节点速查
- 属性复制:AttributeSet + OnRep
- GA 取消:
AbilitySystemComponent->CancelAbilities - Tag 状态:GAS 文档的 Tag 专章(https://www.wanxiangyundang.top/read/unreal-engine-5-8-docs/gameplay-ability-system-compon-ed85)
与 0102 分层的对应
这条链路就是分层架构的活例子: - L1(战斗)抛事件 OnHealthChanged -> L3(UI/特效)订阅 -> L2(世界)监听 OnActorDied 做刷怪计数与掉落 -> L4(联机)复制属性与 Tag。每一层只用自己该用的接口。
心得:把这条链路跑通的那晚,我把项目里所有"直接改血"的地方全删了——代码量少了一半,bug 少了 80%。这是我对 GAS 从"忍受"到"享受"的转折点:纪律在前期是负担,后期是复利。
