언리얼 GAS 사용법 4
태그 부여 방식
TIL - GAS 어빌리티 활성화와 태그 관리
1. TryActivateAbilityByClass는 정확한 클래스 매칭
문제
TryActivateAbilityByClass는 내부적으로 아래처럼 동작함.
1
Spec.Ability->GetClass() == InAbilityClass
== 비교라서 상속 관계를 무시하고 정확히 같은 클래스만 찾음.
1
2
3
4
DefaultAbilities에 등록: BP_GA_Stun (class = BP_GA_Stun)
TryActivateAbilityByClass(GA_Stun) (class = GA_Stun)
BP_GA_Stun == GA_Stun → false → 활성화 실패
C++에서 부모/자식 체크는 IsA<>(), Cast<>() 로 하는데, 이 함수는 의도적으로 exact match를 사용하기 때문에 BP 자식 클래스는 찾지 못함.
해결 - 태그 기반 활성화
어빌리티에 식별용 태그를 붙이고, 클래스 대신 태그로 활성화. 클래스가 무엇이든 태그만 일치하면 동작함.
1
2
// GA_Stun 생성자 - 어빌리티 식별 태그 등록
AbilityTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Stun")));
1
2
3
4
// 활성화하는 쪽 - 태그로 찾아서 활성화
FGameplayTagContainer Tag;
Tag.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Stun")));
TargetASC->TryActivateAbilitiesByTag(Tag);
BP_GA_Stun이 GA_Stun을 상속하면 AbilityTags도 상속되므로 별도 설정 없이 태그 기반 활성화가 동작함.
2. 태그를 어디서 전달할 것인가 - GA vs GE
태그를 부여하는 방법은 GA와 GE 두 가지가 있음. 태그의 생명주기가 무엇에 묶여 있는가에 따라 선택.
GA에서 태그 전달 - ActivationOwnedTags
1
2
// GA 생성자
ActivationOwnedTags.AddTag(FGameplayTag::RequestGameplayTag("State.Stun"));
태그가 어빌리티의 생명주기에 묶임. 어빌리티가 활성화되면 자동 부여, EndAbility 호출 시 자동 제거.
1
2
ActivateAbility() → State.Stun 부여
EndAbility() → State.Stun 제거
적합한 경우:
- 태그의 지속 시간 = 어빌리티 실행 시간
- GA 안에서 WaitDelay, WaitGameplayEvent 등으로 종료 시점을 직접 제어할 때
- GE 없이 단순히 “이 어빌리티가 실행 중이다” 상태를 표현할 때
GE에서 태그 전달 - Granted Tags
1
2
3
4
// GE 컴포넌트 (UE 5.3+)
FInheritedTagContainer TagContainer;
TagContainer.Added.AddTag(FGameplayTag::RequestGameplayTag("State.Stun"));
TagsComp->SetAndApplyTargetTagChanges(TagContainer);
태그가 GE의 생명주기에 묶임. GE가 적용되면 부여, GE가 만료되면 자동 제거.
1
2
GE Apply (Duration 1s) → State.Stun 부여
GE Expire → State.Stun 제거
적합한 경우:
- 태그의 지속 시간 = GE Duration (수치로 명확히 정의)
- HP 감소, 속도 변화 등 Attribute 수치 변경과 태그를 함께 처리할 때
- GA 없이 여러 소스(플랫폼, 함정, 적 등)가 동일한 GE를 독립적으로 적용할 때
스턴에서의 선택
1
2
3
4
5
GA_Stun (WaitDelay 1초로 종료 시점 제어)
└── ActivationOwnedTags → State.Stun ✅
GE_Stun (Duration 1초)
└── Granted Tags → State.Stun ❌ 중복
GA가 이미 1초 후 EndAbility를 호출하며 태그를 제거하므로 GE에서 태그를 추가로 부여할 필요가 없음. GE는 Duration 정의 역할만 하고, 태그는 GA가 책임지는 구조.
3. ActivationBlockedTags로 중복 활성화 방지
문제
플랫폼이 움직이면서 캐릭터에 지속적으로 NotifyHit가 발생. 매 프레임마다 TryActivateAbilitiesByTag가 호출되면서 어빌리티가 중복 활성화됨.
1
2
3
4
Frame 1: NotifyHit → TryActivate → GA_Stun 활성화 → State.Stun(1)
Frame 2: NotifyHit → TryActivate → GA_Stun 재활성화 → State.Stun(2)
Frame 3: NotifyHit → TryActivate → GA_Stun 재활성화 → State.Stun(3)
...
해결 - ActivationBlockedTags
이미 특정 태그가 붙어있을 때 어빌리티 활성화를 차단하는 기능.
1
2
// GA_Stun 생성자
ActivationBlockedTags.AddTag(FGameplayTag::RequestGameplayTag(FName("State.Stun")));
1
2
3
Frame 1: NotifyHit → TryActivate → 활성화 성공 → State.Stun(1) 부여
Frame 2: NotifyHit → TryActivate → State.Stun 태그 감지 → 활성화 차단 ✅
Frame 3: NotifyHit → TryActivate → State.Stun 태그 감지 → 활성화 차단 ✅
핵심 구조 요약
1
2
3
4
5
6
UGA_Stun::UGA_Stun()
{
AbilityTags.AddTag("Ability.Stun"); // 식별 태그 (활성화에 사용)
ActivationOwnedTags.AddTag("State.Stun"); // 활성화 중 부여되는 태그
ActivationBlockedTags.AddTag("State.Stun"); // 이미 스턴 중이면 재활성화 차단
}
ActivationOwnedTags와 ActivationBlockedTags에 같은 태그를 등록하면 자기 자신이 실행 중일 때 재실행을 막는 자연스러운 중복 방지가 됨.