GAS는 Gameplay Ability System의 약자다.
Unreal Engine에서 캐릭터의 스킬, 버프, 디버프, 데미지, 체력, 쿨타임, 코스트, 상태 이상
같은 게임플레이 로직을 체계적으로 만들기 위한 프레임워크


핵심 요소

GAS
 ├─ AbilitySystemComponent
 ├─ GameplayAbility
 ├─ GameplayEffect
 ├─ AttributeSet
 ├─ GameplayTag
 ├─ GameplayCue
 └─ GameplayAbilitySpec
  1. Character 또는 PlayerState에 ASC(AbilitySystemComponent) 추가
  2. AttributeSet 생성
  3. ASC 초기화 InitAbilityActorInfo()
  4. Ability GiveAbility()
  5. 입력에서 TryActivateAbility()
  6. GameplayEffect로 Attribute 변경

AbilitySystemComponent (ASC)

  • Ability 부여
    ASC에 FGameplayAbilitySpec을 넣는 단계
    GiveAbility()
  • Ability 활성화
    이미 부여된 AbilitySpecHandle을 실행 시도하는 단계
    TryActivateAbility()
  • GameplayEffect 적용
  • Attribute 관리
  • GameplayTag 관리
  • 네트워크 복제
AbilitySystemComponent->InitAbilityActorInfo(this, this);

AbilitySystemComponent->GiveAbility(
    FGameplayAbilitySpec(JumpAbilityClass, 1)
);

AbilitySystemComponent->TryActivateAbility(JumpAbilityHandle);

캐릭터가 죽고 리스폰되어도 PlayerState는 유지되기 때문에
멀티플레이에서는 PlayerStateASC를 둔다

GameplayAbility

실제 스킬이나 행동 처리

  • 입력 처리
  • 쿨타임 확인
  • 코스트 확인
  • 대상 찾기
  • GameplayEffect 적용
  • Montage 재생
  • Projectile 생성
  • GameplayCue 실행
  • Ability 종료
virtual bool CanActivateAbility(/**/) override;
virtual void SetCanBeCanceled(/**/) override;
virtual void OnGiveAbility(/**/) override;
virtual void OnRemoveAbility(/**/) override;
virtual void ActivateAbility(/**/) override;
virtual void EndAbility(/**/) override;
virtual bool CheckCost(/**/) override;
virtual void ApplyCost(/**/) override;
virtual FGameplayEffectContextHandle MakeEffectContext(/**/) override;
virtual void ApplyAbilityTagsToGameplayEffectSpec(/**/) override;
virtual bool DoesAbilitySatisfyTagRequirements(/**/) override;

Lyra Jump 예시

bool ULyraGameplayAbility_Jump::CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags, const FGameplayTagContainer* TargetTags, FGameplayTagContainer* OptionalRelevantTags) const
{
    if (!ActorInfo || !ActorInfo->AvatarActor.IsValid())
        return false;

    const ALyraCharacter* LyraCharacter = Cast<ALyraCharacter>(ActorInfo->AvatarActor.Get());
    if (!LyraCharacter || !LyraCharacter->CanJump())
        return false;

    if (!Super::CanActivateAbility(Handle, ActorInfo, SourceTags, TargetTags, OptionalRelevantTags)) 
        return false;

    return true;
}

image-1781543874454

GameplayTag

상태나 분류를 표현하는 태그, GameplayMessageRouter Plugin 2 참고

AttributeSet

캐릭터의 수치 데이터 모음
FGameplayAttributeData로 데이터 관리한다.
BaseValueCurrentValue를 두어 따로 관리한다.

class ULyraCombatSet : public ULyraAttributeSet
{
    GENERATED_BODY()

public:

    ULyraCombatSet();

    UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_BaseDamage, Category = "Lyra|Combat", Meta = (AllowPrivateAccess = true))
    FGameplayAttributeData BaseDamage;

    UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_BaseHeal, Category = "Lyra|Combat", Meta = (AllowPrivateAccess = true))
    FGameplayAttributeData BaseHeal;

    ATTRIBUTE_ACCESSORS(ULyraCombatSet, BaseDamage);
    ATTRIBUTE_ACCESSORS(ULyraCombatSet, BaseHeal);

Lrya에서는 MACROBaseValueCurrentValue를 설정한다.

#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
    GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
    GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
    GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
    GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
#define GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
    inline float Get##PropertyName() const \
    { \
        return PropertyName.GetCurrentValue(); \
    }

#define GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
    inline void Set##PropertyName(float NewVal) \
    { \
        UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent(); \
        if (ensure(AbilityComp)) \
        { \
            AbilityComp->SetNumericAttributeBase(Get##PropertyName##Attribute(), NewVal); \
        }; \
    }

#define GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName) \
    inline void Init##PropertyName(float NewVal) \
    { \
        PropertyName.SetBaseValue(NewVal); \
        PropertyName.SetCurrentValue(NewVal); \
    }

GameplayEffect

AttributeTag를 변경하는 데이터
UGameplayEffect는 기본적으로 데이터 중심 클래스여서
Effect의 대부분은 코드로 새 클래스를 만들 필요 없다.
블루프린트로 Asset을 만들어서 사용한다.

image-1781548758105

  • Attribute 변경
  • GameplayTag 부여
  • 지속 시간 관리
  • 주기적 효과 처리
  • Stack 관리
  • Cooldown 표현
  • Cost 처리

GameplayCue

GameplayEffect와 연결되는 연출 시스템을 담음

  • 피격 이펙트
  • 버프 이펙트
  • 폭발 이펙트
  • 사운드
  • 카메라 쉐이크
  • 나이아가라 이펙트
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_GameplayCue_Character_Spawn);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_GameplayCue_Interact_WeaponPickup);
+GameplayTagList=(Tag="GameplayCue.Character.DamageTaken",DevComment="")
+GameplayTagList=(Tag="GameplayCue.Character.Dash",DevComment="")
+GameplayTagList=(Tag="GameplayCue.Character.Dash.Cooldown",DevComment="Cooldown for character dash")
+GameplayTagList=(Tag="GameplayCue.Character.Death",DevComment="")
+GameplayTagList=(Tag="GameplayCue.Character.Heal",DevComment="")
+GameplayTagList=(Tag="GameplayCue.Character.Melee.Cooldown",DevComment="")

만드는 방법은 GameplayTag와 동일하다. 내부적으로 "GameplayCue"를 달고 있는 Tag만 GameplayEffect의 GameplayCue의 Tag로 띄운다.

image-1781549488414

FGameplayAbilitySpec

ASC가 보유한 Ability 한 개에 대한 등록 정보

GA_FireWeapon 클래스
= 총 쏘기 Ability 정의

FGameplayAbilitySpec
 ├─ Ability = GA_FireWeapon
 ├─ Level = 5
 ├─ InputTag = InputTag.Ability.Fire
 └─ Handle = B

Ability 목록을 확인하거나,
현재 활성 Ability를 확인 하거나,
입력을 연결하거나,
Level 관리 용도로 주로 사용된다.

반응형

'Unreal Engine' 카테고리의 다른 글

UE Game play Framework 1  (0) 2026.06.17
GAS 2  (0) 2026.06.16
SmartObject 1  (0) 2026.06.12
GameplayMessageRouter Plugin 2  (1) 2026.06.11
GameplayMessageRouter Plugin 1  (0) 2026.06.10