Gameplay Abilities
게임에서 액터가 사용하는 스킬이나 액션 등을 나타내기 위해 사용됨.
UGameplayAbility 클래스에서 파생됨.
어빌리티가 발동 가능한 조건(Cost, Cooldown)과 사용 시의 효과 등을 정의함.
함수가 아니라, 비동기적이며 독립적으로 실행되는 인스턴스 가능한 오브젝트임.
따라서 원하는 타이밍에 발동되어, 여러 종류의 AbilityTask를 실행할 수 있음.
AbilityTask는 일정 시간 경과하며 남아있을 수도 있고, 순간적으로 적용될 수도 있음.
이를 통해 플레이어의 체력을 감소시키거나, SFX를 재생하고 VFX를 표현하는 것 등이 가능함.


GameplayEffect와 마찬가지로, 내부적으로 Replication, Prediction (예측)이 지원됨.
GameplayAbility를 사용하기 위해서는 AbilitySystemComponent가 GameplayAbility를 획득 (Grant) 해야 함. GamplayAbility를 획득하면 FGameplayAbilitySpec이 생성되며, 이 Spec을 통해 해당 GameplayAbility에 대한 세부 정보를 얻을 수 있음.

Activation 개념이 담겨 있어, Activate된 이후 자체적으로 종료(End)되거나, 혹은 다른 요소에 의해 중단(Cancel)될 때까지 남아있음.
Granting Abilities
```cpp
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "AbilitySystemInterface.h"
#include "Interaction/CombatInterface.h"
#include "AuraCharacterBase.generated.h"
class UAbilitySystemComponent;
class UAttributeSet;
class UGameplayEffect;
class UGameplayAbility;
UCLASS(Abstract)
class AURA_API AAuraCharacterBase : public ACharacter, public IAbilitySystemInterface, public ICombatInterface
{
GENERATED_BODY()
public:
AAuraCharacterBase();
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
UAttributeSet* GetAttributeSet() const { return AttributeSet; }
protected:
virtual void BeginPlay() override;
virtual void InitAbilityActorInfo();
void ApplyEffectToSelf(TSubclassOf<UGameplayEffect> GameplayEffectClass, float Level) const;
void InitializeDefaultAttributes() const;
void AddCharacterAbilities();
// ...
private:
UPROPERTY(EditAnywhere, Category = "Abilities")
TArray<TSubclassOf<UGameplayAbility>> StartupAbilities;
};
```
```cpp
// AuraCharacterBase.cpp
void AAuraCharacterBase::AddCharacterAbilities()
{
if (!HasAuthority()) return;
UAuraAbilitySystemComponent* AuraASC = Cast<UAuraAbilitySystemComponent>(AbilitySystemComponent);
AuraASC->AddCharacterAbilities(StartupAbilities);
}
```
- GameplayAbility의 획득은 AbilitySystemComponent에서 처리하나, 해당 처리 자체를 플레이어가 캐릭터를 소유하는 시점에 처리하는 것이 현재로선 가장 바람직해 보이기 때문에, AuraCharacterBase에서 AbilitySystemComponent에 GameplayAbility를 추가하라고 명령하는 함수를 정의하는 것이다.
GameplayAbility를 획득하는 것은 서버에서 처리하고, FGameplayAbilitySpec이 소유 클라이언트로 Replicate되는 것이므로, 서버가 아니면 실행되지 않도록 HasAuthority()를 통해 서버가 아니면 실행되지 않도록 처리해준다.
- AbilitySystemComponent의 AddCharacterAbilities()는 AuraCharacterBase에서 선언한 StartupAbilities 배열을 통해 실제로 GameplayAbility를 추가해주는 역할을 하는 별도의 함수다.
```cpp
// AuraAbilitySystemComponent.cpp
void UAuraAbilitySystemComponent::AddCharacterAbilities(const TArray<TSubclassOf<UGameplayAbility>> StartupAbilities)
{
for (TSubclassOf<UGameplayAbility> AbilityClass : StartupAbilities)
{
FGameplayAbilitySpec Spec = FGameplayAbilitySpec(AbilityClass, 1);
// GiveAbility(Spec);
GiveAbilityAndActivateOnce(Spec);
}
}
```
- GameplayAbility를 추가하기 위해선 우선 FGameplayAbilitySpec을 생성해야 하며, 생성자에 UGameplayAbility 클래스와 Ability의 레벨을 넘겨주면 된다.
- GiveAbility()와 GiveAbilityAndActivateOnce()의 차이점은 함수명 그대로, GameplayAbility를 획득하기만 할 것인지, 혹은 획득하고 1회 사용할 것인지의 차이다.
- AuraPlayerCharacter의 PossessedBy()에서 AddCharacterAbilities()를 호출하여 이를 통해 AuraAbilitySystemComponent의 AddCharacterAbilities()를 호출함으로서 GameplayAbility들이 획득되도록 한다.
```cpp
void AAuraPlayerCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
/** Init Ability Actor Info for Server */
InitAbilityActorInfo();
AddCharacterAbilities();
}
```

Settings on Gameplay Abilities
GameplayAbility 블루프린트 내의 세팅

AbilityTag: 이 GameplayAbility가 갖는 GameplayTag
CancelAbilitiesWithTag: 여기에 포함된 GameplayTag를 갖는 다른 GameplayAbility들의 작동을 중단시킴
BlockAbilitiesWithTag: 이 GameplayAbility가 작동 중인 동안 여기에 포함된 GameplayTag를 갖는 다른 GameplayAbility의 작동을 방지함.
ActivationOwnedTags: 이 GameplayAbility가 작동 중인 동안 이 GameplayAbility를 발동하는 소유 액터에게 추가할 GameplayTag임. AbilitySystemGlobals의 ReplicateActivationOwnedTags가 true인 경우 이 GameplayTag 추가는 Replicate 됨
ActivationRequiredTags: 이 GameplayAbility를 사용하는 액터/컴포넌트가 여기에 명시된 모든 GameplayTag를 소유해야만이 이 GameplayAbility를 사용 가능함.
ActivationBlockedTags: 이 GameplayAbility를 사용하는 액터/컴포넌트가 여기에 명시된 모든 GameplayTag 중 하나라도 소유한 경우 이 GameplayAbility는 사용 불가능함.
SourceRequiredTags: 이 GameplayAbility를 사용하는 액터/컴포넌트가 여기에 명시된 모든 GameplayTag를 소유해야만이 이 GameplayAbility를 사용 가능함.
(Source와 Activating의 차이점이 무엇인지는 아직 불명확함
→ 예를 들어, 마법사가 파이어볼을 시전한 경우를 생각해보면 될 것 같기도?
데미지는 파이어볼에서 적용되지만, 이를 시전한 것은 마법사임)
SourceBlockedTags: 이 GameplayAbility를 사용하는 액터/컴포넌트가 여기에 명시된 모든 GameplayTag 중 하나라도 소유한 경우 이 GameplayAbility는 사용 불가능함.
TargetRequiredTags: 대상 액터/컴포넌트가 여기에 명시된 모든 GameplayTag를 소유해야만이 이 GameplayAbility를 사용 가능함.
TargetBlockedTags: 대상 액터/컴포넌트가 여기에 명시된 모든 GameplayTag 중 하나라도 소유한 경우 이 GameplayAbility는 사용 불가능함.
Advanced
Instancing Policy

Net Execution Policy

Costs
Triggers
Cooldowns
이 GameplayAbility를 사용하기 위한 쿨타임 개념을 GameplayEffect 클래스의 형태로 설정할 수 있음.
사용하지 않기를 권장하는 옵션
