[Unreal Engine5] GAS의 GameplayEffectContextHandle과 GameplayEffectSpecHandle

2026. 4. 20. 20:22·프로그래밍/Unreal Engine 5

 

계기

SMASkillProjectile에서 투사체가 적에게 맞았을 때 데미지를 적용하는 코드를 작성하다가 두 핸들의 역할이 헷갈렸다.

FGameplayEffectContextHandle ContextHandle = SourceASC->MakeEffectContext();
ContextHandle.AddInstigator(Avatar, Controller);

FGameplayEffectSpecHandle SpecHandle = SourceASC->MakeOutgoingSpec(DamageEffectClass, 1.f, ContextHandle);
SpecHandle.Data->SetSetByCallerMagnitude(SMSkillTag::Data_Damage_Amount, -BaseDamage);

TargetASC->ApplyGameplayEffectSpecToSelf(*SpecHandle.Data.Get());

왜 두 개를 따로 만들어야 하는지, 그냥 하나로 합칠 수 없는지 의문이 생겼다.


GameplayEffectContextHandle — 출처 증명서

"누가, 어떤 상황에서 이 GE를 발동했는가" 에 대한 메타데이터를 담는 구조체다.

FGameplayEffectContextHandle Context = ASC->MakeEffectContext();
Context.AddInstigator(Avatar, Controller); // 시전자 + 컨트롤러
Context.AddOrigin(GetActorLocation());     // 발동 위치
Context.AddHitResult(HitResult);          // 피격 정보

GE가 적용될 때 부가 정보를 함께 전달하는 봉투 역할을 한다. 이 정보는 이후 아래와 같은 곳에서 꺼내 쓴다.

  • 데미지 계산 시 Instigator 귀속
  • GameplayCue의 피격 위치/방향
  • 어트리뷰트 변경 이벤트에서 누가 때렸는지 추적

GameplayEffectSpecHandle — 실행 계획서

"어떤 GE를, 어떤 수치로 적용할 것인가" 에 대한 실행 설계도다.

FGameplayEffectSpecHandle Spec = ASC->MakeOutgoingSpec(DamageEffectClass, Level, Context);
Spec.Data->SetSetByCallerMagnitude(Tag, -100.f); // 수치 런타임 주입
Spec.Data->DynamicGrantedTags.AddTag(CooldownTag); // 태그 런타임 추가

ContextHandle을 내부에 포함하면서, 실제로 적용될 GE의 클래스, 레벨, 수치, 태그 등 모든 정보를 담고 있다.


둘의 관계

ContextHandle          →    SpecHandle              →    ApplyGameplayEffectSpecToSelf
(누가 / 어디서 / 어떻게)      (무엇을 / 얼마나 / 어떤 태그)      (실제 적용)

SpecHandle이 ContextHandle을 포함하는 구조다. ContextHandle 없이 Spec을 만드는 것도 가능하지만, 그 경우 GE는 적용되어도 시전자 정보가 없어서 Instigator가 None으로 남는다.


핵심 정리

ContextHandle SpecHandle

역할 출처 증명서 실행 계획서
담는 것 시전자, 위치, 피격 정보 GE 클래스, 수치, 태그
포함 관계 — ContextHandle을 내부에 포함
없으면 Instigator 추적 불가 GE 적용 자체가 불가

ContextHandle은 "누가 쐈는지", SpecHandle은 "무엇을 얼마나 쐈는지"다.
출처 없이 계획만 있으면 GE는 적용되지만, 누가 쐈는지 게임이 모른다.

'프로그래밍 > Unreal Engine 5' 카테고리의 다른 글

[Unreal Engine5] GA_SkillBase 리팩토링 회고 — 애니메이션 추가와 GameplayCue owner 복제 이슈  (1) 2026.04.21
[Unreal Engine 5] GAS_멀티플레이에서 GameplayCue가 작동하는 방식  (1) 2026.04.17
[Unreal Engine 5] 멀티플레이 아키텍처: GAS 퀵슬롯과 인벤토리 설계  (0) 2026.04.09
[Unreal Engine 5] 멀티플레이어 디버깅 유틸리티 & WorldContext  (0) 2026.04.06
[Unreal Engine 5] Module과 Plugin의 차이점  (0) 2026.04.02
'프로그래밍/Unreal Engine 5' 카테고리의 다른 글
  • [Unreal Engine5] GA_SkillBase 리팩토링 회고 — 애니메이션 추가와 GameplayCue owner 복제 이슈
  • [Unreal Engine 5] GAS_멀티플레이에서 GameplayCue가 작동하는 방식
  • [Unreal Engine 5] 멀티플레이 아키텍처: GAS 퀵슬롯과 인벤토리 설계
  • [Unreal Engine 5] 멀티플레이어 디버깅 유틸리티 & WorldContext
hanong8
hanong8
hanong8 님의 블로그 입니다.
  • hanong8
    HaNong
    hanong8
  • 전체
    오늘
    어제
    • 분류 전체보기 (101) N
      • 프로그래밍 (98) N
        • Unreal Engine 5 (45)
        • C++ (22)
        • UML (2)
        • 자료구조 (2)
        • 알고리즘 (9)
        • 개발일지 (4)
        • DirectX11 (5)
        • Git (2)
        • 코드카타 (7) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
hanong8
[Unreal Engine5] GAS의 GameplayEffectContextHandle과 GameplayEffectSpecHandle
상단으로

티스토리툴바