
Gameplay Ability는 게임에서 액터가 수행할 수 있는 모든 행동이나 스킬입니다. 예를 들어, 질주하면서 총을 쏘는 것처럼 둘 이상의 GameplayAbility를 동시에 활성화할 수도 있습니다.
Gameplay Ability는 블루프린트 또는 C++에서 구현할 수 있습니다.
GameplayAbility의 예시:


우선 GameplayAbility 클래스를 부모로 삼는 GA_TestAbility를 생성하겠습니다.
// GA_TestAbility.h
#pragma once
#include "CoreMinimal.h"
#include "Abilities/GameplayAbility.h"
#include "GA_Test.generated.h"
/**
*
*/
UCLASS()
class GASTEMPLATE_API UGA_Test : public UGameplayAbility
{
GENERATED_BODY()
public:
UGA_Test();
/** 이 능력을 지금 활성화할 수 있는지 여부를 반환합니다. 부작용은 없습니다. */
virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const override;
/** 실행당 인스턴스화된 능력을 제거합니다. 액터당 인스턴스화된 능력은 '재설정'해야 합니다. 활성 상태의 능력 상태 태스크는 'OnAbilityStateInterrupted' 이벤트를 수신합니다. 비인스턴스 능력 - 무엇을 할 수 있을까요? */
virtual void CancelAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateCancelAbility) override;
/** 능력을 커밋합니다. */
virtual bool CommitAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) override;
/** 실제로 Ability를 활성화합니다. 이 메서드를 직접 호출하지 마세요. */
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
/** Ability가 정상적으로 또는 비정상적으로 종료되었을 때 호출되는 네이티브 함수입니다. bReplicate가 true로 설정된 경우, 클라이언트/서버에 종료를 복제하려고 시도합니다. */
virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override;
};
// GA_TestAbility.cpp
#include "GAS/Abilities/GA_Test.h"
UGA_Test::UGA_Test()
{
// GameplayAbility가 활성화될 때마다 액터마다 새로운 인스턴스가 생성됩니다.
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
}
bool UGA_Test::CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags, const FGameplayTagContainer* TargetTags, OUT FGameplayTagContainer* OptionalRelevantTags) const
{
return true;
}
void UGA_Test::CancelAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateCancelAbility)
{
}
bool UGA_Test::CommitAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags)
{
return true;
}
void UGA_Test::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
UE_LOG(LogTemp, Warning, TEXT("GA_Test::ActivateAbility"));
EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
}
void UGA_Test::EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled)
{
Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
UE_LOG(LogTemp, Warning, TEXT("GA_Test::EndAbility"));
}
Gameplay Ability는 기본적으로 어빌리티를 실행, 취소, 종료, 확인 등을 위한 다양한 함수들을 기본적으로 제공하고 있습니다.
Ability System Component(ASC)에서 TryActivateAbility함수를 통해 해당 어빌리티를 호출하면 자동적으로 ActiveAbility함수가 호출되어 어빌리티의 로직을 실행하게 됩니다.
C++과 마찬가지로 GameplayAbility 클래스를 부모로 삼는 GA_TestAbility를 생성하면 됩니다.

어빌리티를 실행하기 위해서는 다음과 같은 과정이 필요합니다.
GiveAbility를 통해 실행할 어빌리티를 등록하기TryActivateAbility로 등록한 어빌리티를 실행하기// YourCharacter.h
class AGASTemplateCharacter : public ACharacter, public IAbilitySystemInterface
{
GENERATED_BODY()
...
// 어빌리티 시스템 컴포넌트에 추가할 어빌리티입니다.
UPROPERTY(EditAnywhere, Category = GAS)
TSubclassOf<class UGameplayAbility> Ability;
// YourCharacter.cpp
#include "GAS/Abilities/GA_Test.h"
...
void AGASTemplateCharacter::BeginPlay()
{
Super::BeginPlay();
// 캐릭터가 소유한 AbilitySystemComponent를 초기화합니다.
if (AbilitySystemComponent)
{
// OnwerActor : 캐릭터 자신, AvatarActor : 캐릭터 자신
AbilitySystemComponent->InitAbilityActorInfo(this, this);
// AbilitySystemComponent에 Ability를 등록합니다.
FGameplayAbilitySpec TestAbilitySpec(UGA_Test::StaticClass());
AbilitySystemComponent->GiveAbility(TestAbilitySpec);
}
}
void AGASTemplateCharacter::ActiveAbility(const FInputActionValue& Value)
{
bool BoolValue = Value.Get<bool>();
if (BoolValue)
{
// AbilitySystemComponent에서 UGA_Test Ability를 찾습니다.
FGameplayAbilitySpec* AbilitySpec = AbilitySystemComponent->FindAbilitySpecFromClass(UGA_Test::StaticClass());
if (AbilitySpec)
{
// Ability를 실행합니다.
AbilitySystemComponent->TryActivateAbility(AbilitySpec->Handle); // Ability Spec을 통해 Ability를 실행합니다.
//AbilitySystemComponent->TryActivateAbilityByClass(UGA_Test::StaticClass()); // Ability Class를 통해 Ability를 실행합니다.
//AbilitySystemComponent->TryActivateAbilitiesByTag(FGameplayTagContainer::EmptyContainer); // Ability Tag를 통해 Ability를 실행합니다.
}
else
{
UE_LOG(LogTemplateCharacter, Error, TEXT("Failed to find ability spec for GA_Test"));
}
}
}
이러면 이제 ASC를 이용하여 우리가 원하는 어빌리티들을 실행할 수 있게 됩니다.

TryActiveAbility를 통해 실행
실행 방법에도 총 3가지가 있습니다.
세가지 방법 모두 C++, 블루프린트에서 자유롭게 사용이 가능합니다.
Gameplay Tag에 대해서는 추후 더 자세히 다루겠습니다.
실행할 키를 바인드하고 어빌리티를 실행시켜보면 다음과 같이 로그가 뜨게 됩니다.

📘 TIP Gameplay Ability는 기본적으로 한프레임에 실행이 됩니다.
따라서 애니메이션이나 이벤트와 같은 대기 작업이 필요한 경우 Ability Task를 통해 지연 작업을 사용하게 됩니다.
Ability Task에 관한 내용 역시 추후에 더 자세히 다루겠습니다.