常见坑:负血、属性上限与 Clamp
GE 走通后,四个数值边界问题几乎必然出现。
坑一:血量变成负数
Instant GE 扣 100 血,角色只有 30 血 → CurrentValue = -70。GAS 不会自动 clamp。
解法:在 AttributeSet 的 PostGameplayEffectExecute 里守门:
void UMyAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
SetHealth(FMath::Clamp(GetHealth(), 0.f, GetMaxHealth()));
}
为什么用 PostGameplayEffectExecute 而不是 PreAttributeChange:Pre 在"修改前"被调用(可取消),Post 在修改完成后——clamp 放 Post 最直接,且能广播 UI。
官方推荐:PreAttributeChange 用于"在修改前 clamp 输入值"(如回血不超上限),PostGameplayEffectExecute 用于"clamp 结果并做副作用"(如死亡判定、UI 通知)。
坑二:上限改变了但当前值没跟上
MaxHealth 从 100 → 150(升级),Health 还是 100。
解法:升级 GE 的 Modifier 配 Attribute Based:当 MaxHealth 变化时,Health 也加差值(配一个 Derived Attribute,或在 Post 同步处理)。常见做法是升级时同时应用一个"回满血" GE,UX 上也合理。
坑三:Buff/Debuff 与装备属性混在一起
装备给的 +30 攻击是 Infinite GE,中毒的 -20 是 Duration GE,驱散时会不会一起被清掉?
解法:靠标签严格区分来源:
- 装备 GE:Effect.Source.Gear;
- Buff/Debuff:Effect.Buff / Effect.Debuff;
- 驱散只查 Effect.Debuff,装备属性毫发无损。
坑四:UE 属性变化的"消息顺序"
同一帧多个 GE 应用(范围伤害 10 个目标),变化通知的顺序不保证。UI 刷新逻辑不要依赖"先扣血死后扣"这种顺序,做最终状态刷新(订阅时同步一次当前值)。
一个排查工具
GE 体系"静默失败"时:
1. ability.showdebug ability → 看 Active Effects 页签,确认 GE 是否在、剩多久;
2. log GameplaySystem VeryVerbose → 看应用被拒绝的原因(Blocked Tags / 权限);
3. 检查 GE 的 Application Conditions 与标签需求。
本章小结
- 数值 clamp 放 AttributeSet 的 Pre/Post 回调:Pre 管输入、Post 管结果与副作用。
- 属性上限变化时用 Derived Attribute 或"补差/回满" GE 对齐当前值。
- 装备/Buff/Debuff 靠标签分源,驱散按标签精确移除。
