GAS에서 지속 데미지(Burn)가 매 틱 피격 리액션을 유발하는 문제
증상
플레이어가 몬스터에게 Burn(GE_Burn)을 부여하면, 몬스터가 화상 데미지를 받는 매 틱마다 움찔(Flinch) 거리는 현상.
원인 분석
Burn은 Periodic(주기) 데미지라 틱마다 PostGameplayEffectExecute → BroadcastHitEvent가 호출된다.
BroadcastHitEvent는 공격 GE의 asset tag를 읽어 두 개의 이벤트를 발행한다.
| 구분 | 매칭 베이스 태그 | Burn에서의 값 |
|---|---|---|
| 공격자 이벤트 | GameplayEvent.Attack.HitSuccess |
GameplayEvent.Attack.HitSuccess.Burn ✅ |
| 타겟 이벤트 | GameplayEvent.Hit |
Burn엔 Hit.* 태그가 없어 기본값 GameplayEvent.Hit.Normal로 떨어짐 ⚠️ |
→ 타겟(몬스터)에게 매 틱 GameplayEvent.Hit.Normal이 전송됨
→ HitReactionComponent::HandleHitEvent 수신
→ ResolveReactType에서 HitReact.Type.* 태그가 없으면 기본값 Flinch 반환
→ 결국 Burn 틱마다 Flinch 발동
핵심: 피격 리액션 억제는 GE 데미지 처리(CombatAttributeSet) 단계에서 발행되는 GameplayEvent.Hit 이벤트가 트리거다. 데미지 계산과 리액션 발행이 같은 함수에 묶여 있다.
해결
BroadcastHitEvent에서 공격 이벤트가 DoT(Burn)면 타겟 Hit 이벤트만 건너뛴다. 데미지 / 플로터 / AI 인지는 그대로 유지.
EventData.EventTag = AttackerEventTag;
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(AttackerActor, AttackerEventTag, EventData);
// Burn 등 지속 데미지(DoT)는 데미지만 적용하고 피격 반응(움찔/몽타주)은 발생시키지 않는다.
const bool bIsDamageOverTime =
AttackerEventTag.MatchesTag(RetrieveGameplayTags::GameplayEvent_Attack_HitSuccess_Burn);
if (TargetActor != AttackerActor && !bIsDamageOverTime)
{
EventData.EventTag = TargetEventTag;
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(TargetActor, TargetEventTag, EventData);
}
결과
| 항목 | Burn 틱 | 일반 공격 |
|---|---|---|
| 데미지 | ✅ | ✅ |
| 데미지 플로터 | ✅ | ✅ |
| AI 인지 | ✅ | ✅ |
| 피격 리액션 | ❌ (차단) | ✅ |
배운 점 / 확장
MatchesTag를 써서...Burn.X하위 태그가 생겨도 자동 커버.- 데미지 적용 vs 피격 반응을 분리해서 생각해야 한다 — "데미지를 받되 리액션은 안 함"은 이벤트 발행 단계에서 타겟 이벤트만 막는 것으로 해결.
- 추후 독·감전 등 DoT 추가 시
bIsDamageOverTime조건에|| AttackerEventTag.MatchesTag(...)한 줄씩 추가.