https://dev.epicgames.com/documentation/ko-kr/unreal-engine/using-gameplay-abilities-in-unreal-engine?application_version=5.3

 

언리얼 엔진의 게임플레이 어빌리티 사용하기 | 언리얼 엔진 5.4 문서 | Epic Developer Community

게임플레이 어빌리티 클래스의 개요입니다.

dev.epicgames.com

 

https://github.com/tranek/GASDocumentation?tab=readme-ov-file#concepts-ga

 

GitHub - tranek/GASDocumentation: My understanding of Unreal Engine 5's GameplayAbilitySystem plugin with a simple multiplayer s

My understanding of Unreal Engine 5's GameplayAbilitySystem plugin with a simple multiplayer sample project. - tranek/GASDocumentation

github.com

 

  • Game 내 Actor가 하는 모든 행동이나 Skill, Ability가 하는 일, Cost, 조건 및 시점을 정의
  • UGameplayAbility를 상속
  • GA는 비동기로 실행되는 Instance화 된 Object로 존재할 수 있다.
    • 다양한 캐릭터 상호작용에 따른 분기처럼 전문화 된 다단계 Task를 실행할 수 있다.
    • Character Animation, Particle/Sound Effect, Player Input 이나 실행 등
  • Net Execution Policy를 통한 자체 Replicate, Client/Server에서의 실행, 변수 동기화나 RPC 호출도 가능
    • 단, Simulated Proxy에는 호출 불가
  • Game Session 중에 Engine이 GA를 구현하는 방식에 있어 유연성을 제공합니다.
    • Cooldown, Cost, Player Input, Anim Montage Animation, Actor에 부여되는
      Ability 자체에 대한 반응을 구현하는 확장 함수
  • 여러 시간에 걸쳐서 발생하는 Gameplay Ability를 실행하는 데에 Ability Task를 사용
    • Attribute 변경 대기
    • Target 선택 대기
    • Root Motion Source의 캐릭터 움직임 등
  • Simulated client는 Gameplay Ability를 호출하지 않는다.
    • 대신 서버에서 Ability가 동작하고, 시각적으로 재생이 필요한 것들은 모두
      Ability Task나 GameplayCue를 통해 Replicate 된다.
  • BP, C++에서 모두 작업 가능

Bind Input to ASC

  • ASC는 직접적인 Input Bind를 제공하고 이에 대해 GameAbility를 Grant 할 수 있도록 기능을 제공한다.
  • GameAbility에 등록된 Input Action은 Press가 발생할 때 Gameplay Tag 조건을 만족하면
    자동으로 Gameplay Activity로 동작한다.
  • Input Action이 등록된 Input에 반응하려면 내장된 Ability Task를 요구한다.
  • 활성화 된 Gameplay Ability에 등록된 Input Action에 더불어, ASC도 범용적인 Confirm, Cancel Input을 받을 수 있다.
    • 이런 특별한 Input은 Ability Task에서 Target Actor나 Ability 취소와 같은 것들을 등록할 때 사용된다.
  • ASC에 Input을 Bind하려면 가장 먼저 Inpuat Action Name을 byte로 변환하는 Enum을 선언해야 한다.
    • 이 Enum의 이름은 Project Setting에서의 Input Action 이름과 완벽하게 일치해야 한다.
    • DisplayName은 아무 상관 없다.
더보기
UENUM(BlueprintType)
enum class EGDAbilityInputID : uint8
{
	// 0 None
	None			UMETA(DisplayName = "None"),
	// 1 Confirm
	Confirm			UMETA(DisplayName = "Confirm"),
	// 2 Cancel
	Cancel			UMETA(DisplayName = "Cancel"),
	// 3 LMB
	Ability1		UMETA(DisplayName = "Ability1"),
	// 4 RMB
	Ability2		UMETA(DisplayName = "Ability2"),
	// 5 Q
	Ability3		UMETA(DisplayName = "Ability3"),
	// 6 E
	Ability4		UMETA(DisplayName = "Ability4"),
	// 7 R
	Ability5		UMETA(DisplayName = "Ability5"),
	// 8 Sprint
	Sprint			UMETA(DisplayName = "Sprint"),
	// 9 Jump
	Jump			UMETA(DisplayName = "Jump")
};

ASC in Character

  • ACharacter::SetupPlayerInputcomponent() 함수안에서 ASC에 Bind 하는 작업을 추가
더보기
/** Bind to an input component with customized bindings */
virtual void BindAbilityActivationToInputComponent(UInputComponent* InputComponent, FGameplayAbilityInputBinds BindInfo);

void ACharacter::SetupPlayerInputComponent
{
    // Bind to AbilitySystemComponent
    FTopLevelAssetPath AbilityEnumAssetPath = FTopLevelAssetPath(FName("/Script/GASDocumentation"), FName("EGDAbilityInputID"));
    AbilitySystemComponent->BindAbilityActivationToInputComponent(PlayerInputComponent, FGameplayAbilityInputBinds(FString("ConfirmTarget"),
	FString("CancelTarget"), AbilityEnumAssetPath, static_cast<int32>(EGDAbilityInputID::Confirm), static_cast<int32>(EGDAbilityInputID::Cancel)));
}

ASC in PlayerState

  • PlayerState가 아직 Client에 Replicate 되지 않을 수 있어 ACharacter::SetupPlayerInputComponent 안에서
    Race Condition이 발생할 위험이 있다.
  • 때문에 ACharacter::SetupPlayerInputcomponent 뿐 아니라 OnRep_PlayerState() 안에서도 Bind 작업이 필요하다.
  • OnRep_PlayerState() 자체만으로는 Bind 작업에 충분치 않다.
    • PlayerController가 Cliient에서 ClientRestart()를 호출해 InputComponent를 생성하기 전에
      PlayerState가 Replicate 되면 Actor의 InputComponent가 null이 될 수 있기 때문이다.

Bind to Input Without Actiavting Ability

  • Input이 발생할 때 Gameplay Ability가 동작하지는 않지만, Ability Task를 통한 Bind는 계속 유지하고 싶을 때 사용
  • UAbilitySystemComponent::AbilityLocalInputPressed()를 override 하여 Gameplay Ability 작업을 Customize.

Basic Usage

Activation Sequence

Local pretiction

  • TryActivateAbility()
  • InternalTryActivateAbility()
  • CanActivateAbility()
    • Gameplay Tag 조건이 부합한디
    • ASC에서 Cost를 지불할 수 있는지
    • Gameplay Ability가 Cooldown 상태가 아닌지
    • 이미 활성화된 Instance가 없는지
  • CallServerTryActivateAbility()
    • 이 함수를 통하 생성된 Pretiction Key를 전달한다.
  • CallActivateAbility()
  • PreActivate()
    • Epic은 이걸 Boilerplate Init Stuff라 부른다.
  • ActivateAbility()
    • 이 함수에서 비로소 Ability가 동작한다.

Server

  • CallServerTryActivateAbility()에서 RPC를 받으면서 시작
  • ServerTryActivateAbility()
  • InterServerTryActivateAbility()
  • InternalTryActivateAbility()
  • CanActivateAbility()
    • Local Pretiction과 동일한 조건을 체크, 반환
  • ClientActivateAbilitySucced()
    • 다음 두 조건을 만족 하면 호출 됨
      • Server에서 활성화 되는 ActivationInfo가 성공적으로 수정 된 경우.
      • OnConfirmDelegate가 Broadcast 된 경우
  • CallActivateAbility()
  • PreActivate()
  • ActivateAbility()
    • 여기서 Ability가 동작한다.
  • ClientActivateAbilityFailed()
    • Server가 Ability 활성화에 실패한 경우에 호출 된다.
    • 즉시 Client의 Gameplay Ability를 제거하고 적용된 것들을 복구한다.

Grant Ability

  • ASC의 ActivatableAbility에 Gameplay Ability를 추가
    • ActivatableAbility에서 Gameplay Tag 조건이 맞으면 활성화가 된다.
  • Gameplay Ability를 서버에서 등록하면 GameplayAbilitySpec을 소유한 Client에 자동으로 Replicate 한다.
    • 다른 Client나 Simulated Proxy는 GameplayAbilitySpec을 받지 않는다.
    • GameplayAbilitySpec은 Gameplay Ability가 Grant 될 때 생성
    • Ability Level, Bind 된 input, 해당 Gameplay Ability를 ASC에 전달한 Source Object 정보를 담고 있다.

GiveAbility

더보기
/*
 * Grants an Ability.
 * This will be ignored if the actor is not authoritative.
 * Returns handle that can be used in TryActivateAbility, etc.
 * 
 * @param AbilitySpec FGameplayAbilitySpec containing information about the ability class, level and input ID to bind it to.
 */
FGameplayAbilitySpecHandle GiveAbility(const FGameplayAbilitySpec& AbilitySpec);

 

void AGDCharacterBase::AddCharacterAbilities()
{
	// Grant abilities, but only on the server	
	if (Role != ROLE_Authority || !AbilitySystemComponent.IsValid() || AbilitySystemComponent->bCharacterAbilitiesGiven)
	{
		return;
	}

	for (TSubclassOf<UGDGameplayAbility>& StartupAbility : CharacterAbilities)
	{
		AbilitySystemComponent->GiveAbility(
			FGameplayAbilitySpec(StartupAbility, GetAbilityLevel(StartupAbility.GetDefaultObject()->AbilityID), static_cast<int32>(StartupAbility.GetDefaultObject()->AbilityInputID), this));
	}

	AbilitySystemComponent->bCharacterAbilitiesGiven = true;
}
  • FGameplayAbilitySpec으로 추가할 Ability를 나타냄
  • FGameplayAbilitySpecHandle을 반환

GiveAbilityAndActivateOnce

더보기
/*
 * Grants an ability and attempts to activate it exactly one time, which will cause it to be removed.
 * Only valid on the server, and the ability's Net Execution Policy cannot be set to Local or Local Predicted
 * 
 * @param AbilitySpec FGameplayAbilitySpec containing information about the ability class, level and input ID to bind it to.
 * @param GameplayEventData Optional activation event data. If provided, Activate Ability From Event will be called instead of ActivateAbility, passing the Event Data
 */
FGameplayAbilitySpecHandle GiveAbilityAndActivateOnce(FGameplayAbilitySpec& AbilitySpec, const FGameplayEventData* GameplayEventData = nullptr);
  • FGameplayAbilitySpec으로 추가할 Ability를 나타냄
  • FGameplayAbilitySpecHandle을 반환
  • Ability는 반드시 Instance화되고 Server에서 실행할 수 있어야 한다.
    • Server에서 실행을 시도한 후에는 FGameplayAbilitySpecHandle을 반환한다.
  • Ability가 필수 조건을 충족하지 못하거나 실행 할 수 없는 경우,
    Handle이 유효하지 않아 ASC가 Ability를 부여받지 못한다.

Revoke Ability

  • 입력받은 FGameplayAbilitySpecHandle은 모두 Grant 과정에서 반환한 것들을 사용한다.

ClearAbility

더보기
/** 
 * Removes the specified ability.
 * This will be ignored if the actor is not authoritative.
 * 
 * @param Handle Ability Spec Handle of the ability we want to remove
 */
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Gameplay Abilities")
void ClearAbility(const FGameplayAbilitySpecHandle& Handle);
  • 지정한 Ability를 ASC에서 제거한다.

ClearAllAbilities

더보기
/** Wipes all 'given' abilities. This will be ignored if the actor is not authoritative. */
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="Gameplay Abilities")
void ClearAllAbilities();
  • ASC의 모든 Ability를 제거한다.

ClearAllAbilitiesWithInputID

더보기
/**
 * Clears all abilities bound to a given Input ID
 * This will be ignored if the actor is not authoritative
 *
 * @param InputID The numeric Input ID of the abilities to remove
 */
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Gameplay Abilities")
void ClearAllAbilitiesWithInputID(int32 InputID = 0);
  • Input ID에 Bind 된 모든 Ability를 ASC에서 제거한다.

SetRemoveAbilityOnEnd

더보기
/** Sets an ability spec to remove when its finished. If the spec is not currently active, it terminates it immediately. Also clears InputID of the Spec. */
void SetRemoveAbilityOnEnd(FGameplayAbilitySpecHandle AbilitySpecHandle);
  • 지정한 Ability 실행이 완료되면 ASC에서 제거한다.
    • 실행중이지 않는 경우 즉시 제거한다.
    • 실행중인 경우 그 입력을 즉시 지워 Player가 더이상 재활성화/상호작용 못하도록 막는다.

CanActivateAbility

  • 호출자가 Ability 실행을 시도하지 않아도 사용 가능 여부를 알려주는 함수
    • UI에서 Player가 사용할 수 없는 Icon을 Dimd 처리해야 하는 경우
    • Character에 특정 Particle/Sound Effect를 재생해 특정 Ability가 사용 가능한지 Notify해야 하는 경우
더보기
/** Returns true if this ability can be activated right now. Has no side effects */
virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const;

CallActivateAbility

  • Ability에 관련된 Game Code를 실행
    • 하지만 사용 가능 여부를 검사하지 않는다.
  • CanActivateAbility 검사와 Ability 실행 사이에 약간의 로직이 필요한 경우에 실행
  • Actor/Component와 달리 주 작업이 Tick을 수행하지 않는다.
    • 대신 활성화 중 비동기 작업을 시행할 수 있는 Ability Task를 지원 함.
    • C++에서는 Delegate로, BP에서는 실행 핀 노드로 해당 Task 출력을 처리한다.
더보기
/** Executes PreActivate and ActivateAbility */
void CallActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, FOnGameplayAbilityEnded::FDelegate* OnGameplayAbilityEndedDelegate = nullptr, const FGameplayEventData* TriggerEventData = nullptr);

ActivateAbility

  • 사용자가 Ability의 Custom Function 기능으로 Override해야 하는 Main Code
더보기
/** Actually activate ability, do not call this directly */
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData);

CommitAbility

  • Activate 내에서 호출 한 경우 Ability 실행 비용을 적용하는 함수
    • Attribute에서 Game System에 맞는 Resource를 감산하고 쿨다운 적용
더보기
virtual bool CommitAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);
virtual bool CommitAbilityCooldown(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const bool ForceCooldown, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);
virtual bool CommitAbilityCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);

CancelAbility

  • Ability 취소 매커니즘을 제공한다.
    • Ability는 CanBeCanceled 함수가 요청을 거부할 수 있다.
  • CommitAbility와 달리 Ability 자체 외부 호출자에서 사용할 수 있다.
  • 취소가 성공하면 다음 작업이 이어진다.
    • OnGameplayAbilityCancelled로 Broadcast
    • 해당 Ability를 종료하기 위한 표준 Code 경로로 이동
    • Ability에 특수한 Cleanup Code를 실행할 기회를 주거나,
      정상적으로 종료했을 때와 다른 동작을 하도록 함.
  • RemoteEndOrCancelAbility()에서 WasCancelled 파라미터를 true로 설정하면 내부에서 CalcelAbility가 호출된다.
더보기
/** Cancels the specified ability CDO. */
void CancelAbility(UGameplayAbility* Ability);	

/** Cancels the ability indicated by passed in spec handle. If handle is not found among reactivated abilities nothing happens. */
void CancelAbilityHandle(const FGameplayAbilitySpecHandle& AbilityHandle);

/** Cancel all abilities with the specified tags. Will not cancel the Ignore instance */
void CancelAbilities(const FGameplayTagContainer* WithTags=nullptr, const FGameplayTagContainer* WithoutTags=nullptr, UGameplayAbility* Ignore=nullptr);

/** Cancels all abilities regardless of tags. Will not cancel the ignore instance */
void CancelAllAbilities(UGameplayAbility* Ignore=nullptr);

/** Cancels all abilities and kills any remaining instanced abilities */
virtual void DestroyActiveState();

TryActivateAbility

  • Ability를 실행하는 전형적인 방식
  • CanActivateAbility를 호출해 실행 여부를 판단한 뒤, 가능하면 CallActivateAbility를 호출
더보기
/** 
 * Attempts to activate every gameplay ability that matches the given tag and DoesAbilitySatisfyTagRequirements().
 * Returns true if anything attempts to activate. Can activate more than one ability and the ability may fail later.
 * If bAllowRemoteActivation is true, it will remotely activate local/server abilities, if false it will only try to locally activate abilities.
 */
UFUNCTION(BlueprintCallable, Category = "Abilities")
bool TryActivateAbilitiesByTag(const FGameplayTagContainer& GameplayTagContainer, bool bAllowRemoteActivation = true);

/**
 * Attempts to activate the ability that is passed in. This will check costs and requirements before doing so.
 * Returns true if it thinks it activated, but it may return false positives due to failure later in activation.
 * If bAllowRemoteActivation is true, it will remotely activate local/server abilities, if false it will only try to locally activate the ability
 */
UFUNCTION(BlueprintCallable, Category = "Abilities")
bool TryActivateAbilityByClass(TSubclassOf<UGameplayAbility> InAbilityToActivate, bool bAllowRemoteActivation = true);

/** 
 * Attempts to activate the given ability, will check costs and requirements before doing so.
 * Returns true if it thinks it activated, but it may return false positives due to failure later in activation.
 * If bAllowRemoteActivation is true, it will remotely activate local/server abilities, if false it will only try to locally activate the ability
 */
UFUNCTION(BlueprintCallable, Category = "Abilities")
bool TryActivateAbility(FGameplayAbilitySpecHandle AbilityToActivate, bool bAllowRemoteActivation = true);

/** Triggers an ability from a gameplay event, will only trigger on local/server depending on execution flags */
bool TriggerAbilityFromGameplayEvent(FGameplayAbilitySpecHandle AbilityToTrigger, FGameplayAbilityActorInfo* ActorInfo, FGameplayTag Tag, const FGameplayEventData* Payload, UAbilitySystemComponent& Component);
  • TriggetAbilityFromGameplayEvent를 사용하려면 해당 Gameplay Ability에 Trigger가 세팅되어 있어야 한다.
    • Gameplay Tag를 할당하고 Gameplay Event 옵션을 활성화 해야 한다.
    • Event를 사용하면 Data를 포함한 Payload에 전달할 수 있다.
  • GameplayTag가 추가/제거 되었을 때 GameplayAbility 활성화를 할 수 있다.
  • Event를 발생하려면 다음 함수를 사용해야 한다.
더보기
//UAbilitySystemBlueprintLibrary
/**
 * This function can be used to trigger an ability on the actor in question with useful payload data.
 * NOTE: GetAbilitySystemComponent is called on the actor to find a good component, and if the component isn't
 * found, the event will not be sent.
 */
UFUNCTION(BlueprintCallable, Category = Ability, Meta = (Tooltip = "This function can be used to trigger an ability on the actor in question with useful payload data."))
static void SendGameplayEventToActor(AActor* Actor, FGameplayTag EventTag, FGameplayEventData Payload);

Passive Ability

  • 자동으로 활성화 되고 계속해서 동작해야 하는 Gameplay Ability
  • UGameplayAbility::OnAvatarSet() 함수를 Override
    • Gameplay Ability가 등록되고 AvatarActor가 세팅되어 TryActivateAbility()가 호출 될 때 자동으로 호출된다.
  • Passive Ability는 기본적으로 Server Only로 동작한다.
더보기
void UGDGameplayAbility::OnAvatarSet(const FGameplayAbilityActorInfo * ActorInfo, const FGameplayAbilitySpec & Spec)
{
	Super::OnAvatarSet(ActorInfo, Spec);

	if (bActivateAbilityOnGranted)
	{
		ActorInfo->AbilitySystemComponent->TryActivateAbility(Spec.Handle, false);
	}
}

Activation Failed Tag

  • Ability는 왜 활성화에 실패했는지 알려주는 기능을 제공하고 있다.
  • 이 기능을 사용하려면 기본적인 실패 케이스에 해당하는 GameplayTag를 세팅하고,
    [Project]/Config/DefaultGame.ini 파일에 등록해야 한다,
  • Project
더보기
+GameplayTagList=(Tag="Activation.Fail.BlockedByTags",DevComment="")
+GameplayTagList=(Tag="Activation.Fail.CantAffordCost",DevComment="")
+GameplayTagList=(Tag="Activation.Fail.IsDead",DevComment="")
+GameplayTagList=(Tag="Activation.Fail.MissingTags",DevComment="")
+GameplayTagList=(Tag="Activation.Fail.Networking",DevComment="")
+GameplayTagList=(Tag="Activation.Fail.OnCooldown",DevComment="")
  • DefaultGame.ini
더보기
[/Script/GameplayAbilities.AbilitySystemGlobals]
ActivateFailIsDeadName=Activation.Fail.IsDead
ActivateFailCooldownName=Activation.Fail.OnCooldown
ActivateFailCostName=Activation.Fail.CantAffordCost
ActivateFailTagsBlockedName=Activation.Fail.BlockedByTags
ActivateFailTagsMissingName=Activation.Fail.MissingTags
ActivateFailNetworkingName=Activation.Fail.Networking

EndAbility

  • Ability 실행을 마치면 Ability를 종료
  • Ability가 취소 된 경우 UGameplayAbility 클래스에서 취소 Process의 일부로 자동 처리를 한다.
    • 하지만 그 외 경우에는 개발자가 C+++ 함수를 호출하거나 BPNode를 추가해야 한다.
  • Ability를 정상적으로 종료하지 못하면 GAS는 아직 실행중으로 판단,
    이후 해당 Ability는 이를 차단하는 다른 Ability를 사용하지 못하게 할 수 있다.
더보기
/** Called by ServerEndAbility and ClientEndAbility; avoids code duplication. */
void	RemoteEndOrCancelAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo ActivationInfo, bool bWasCanceled);

UFUNCTION(Server, reliable, WithValidation)
void	ServerEndAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo ActivationInfo, FPredictionKey PredictionKey);

UFUNCTION(Client, reliable)
void	ClientEndAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo ActivationInfo);

Get ActiveAbilities

  • Active Ability란 존재할 수 없다.
    • 한번에 여러개의 Gameplay Ability가 활성화 될 수 있기 때문이다.
  • 대신 ASC::ActivatableAbilities에서 Asset/Granted/GameplayTag가 일치한 Ability를 검색해야만 한다.
    • GetActivatableAbilities() 함수를 통해 ActivatableAbilities의 TArray<FGameplayAbilitySpec>를 제공한다.
더보기
/** Returns the list of all activatable abilities. Read-only. */
const TArray<FGameplayAbilitySpec>& GetActivatableAbilities() const
{
	return ActivatableAbilities.Items;
}

/** Returns the list of all activatable abilities. */
TArray<FGameplayAbilitySpec>& GetActivatableAbilities()
{
	return ActivatableAbilities.Items;
}
  • 또한 GameplayAbilitySpecs를 수동으로 순회하는 대신 편의 함수를 제공한다.
더보기
/** 
 * Gets all Activatable Gameplay Abilities that match all tags in GameplayTagContainer AND for which
 * DoesAbilitySatisfyTagRequirements() is true.  The latter requirement allows this function to find the correct
 * ability without requiring advanced knowledge.  For example, if there are two "Melee" abilities, one of which
 * requires a weapon and one of which requires being unarmed, then those abilities can use Blocking and Required
 * tags to determine when they can fire.  Using the Satisfying Tags requirements simplifies a lot of usage cases.
 * For example, Behavior Trees can use various decorators to test an ability fetched using this mechanism as well
 * as the Task to execute the ability without needing to know that there even is more than one such ability.
 */
void GetActivatableGameplayAbilitySpecsByAllMatchingTags(const FGameplayTagContainer& GameplayTagContainer, TArray < struct FGameplayAbilitySpec* >& MatchingGameplayAbilities, bool bOnlyAbilitiesThatSatisfyTagRequirements = true) const;
  • bOnlyAbilitiesThatSatisfyTagRequirements
    • 주어진 Gameplay Tag 조건을 만족하고 현재 활성화 되어 있는 GameplayAbilitySpec만 반환할지 여부
  • 한번 FGameplayAbilitySpec을 탐색하면 IsActive()를 호출할 수 있다.

Tags

  • 여러 Gameplay Ability의 상호작용 방식을 결정

Tag Set

  • Ability의 Behaviour에 영향을 미칠수 있는 방식
  • Ability를 식별 및 분류

Gamplay Tag Container

  • 다른 Ability와의 Interaction을 지원

Cancel Abilities With Tag

  • 이 Ability가 실행되는 동안 이미 실행 중인 Ability의 Tag가 제공된 목록과 일치하면 그 Ability를 취소한다.

Block Abilities With Tag

  • 이 Ability가 실행되는 동안 일치하는 Tag가 있는 다른 Ability의 실행을 방지한다.

Activation Owned Tags

  • 이 Ability가 실행되는 동안 해당 Ability의 Owner에 이 Tag Set가 부여된다.

Activation Required Tags

  • 이 Ability는 Active 상태인 Actor/Component에 모든 Tag가 있을 때에만 Activate 할 수 있다.

Activation Blocked Tags

  • 이 Ability는 Active 상태인 Actor/Component에 모든 Tag가 없을 때에만 Activate 할 수 있다.

Target Required Tags

  • 이 Ability는 Target Actor/Component에 이 Tag가 모두 있을 때에만 Activate 할 수 있다.

Target Blocked Tags

  • 이 Ability는 Target Actor/Component에 이 Tag가 모두 없을 때에만 Actiavte 할 수 있다.

Gameplay Tag Query

  • 다른 Ability와의 Interaction을 지원

Gameplay Ability Spec

더보기
/**
 * An activatable ability spec, hosted on the ability system component. This defines both what the ability is (what class, what level, input binding etc)
 * and also holds runtime state that must be kept outside of the ability being instanced/activated.
 */
USTRUCT(BlueprintType)
struct GAMEPLAYABILITIES_API FGameplayAbilitySpec : public FFastArraySerializerItem
{
	GENERATED_USTRUCT_BODY()

PRAGMA_DISABLE_DEPRECATION_WARNINGS
	FGameplayAbilitySpec(const FGameplayAbilitySpec&) = default;
	FGameplayAbilitySpec(FGameplayAbilitySpec&&) = default;
	FGameplayAbilitySpec& operator=(const FGameplayAbilitySpec&) = default;
	FGameplayAbilitySpec& operator=(FGameplayAbilitySpec&&) = default;
	~FGameplayAbilitySpec() = default;
PRAGMA_ENABLE_DEPRECATION_WARNINGS

	FGameplayAbilitySpec()
		: Ability(nullptr), Level(1), InputID(INDEX_NONE), SourceObject(nullptr), ActiveCount(0), InputPressed(false), RemoveAfterActivation(false), PendingRemove(false), bActivateOnce(false)
	{ }

	/** Version that takes an ability class */
	FGameplayAbilitySpec(TSubclassOf<UGameplayAbility> InAbilityClass, int32 InLevel = 1, int32 InInputID = INDEX_NONE, UObject* InSourceObject = nullptr);

	/** Version that takes an ability CDO, this exists for backward compatibility */
	FGameplayAbilitySpec(UGameplayAbility* InAbility, int32 InLevel = 1, int32 InInputID = INDEX_NONE, UObject* InSourceObject = nullptr);

	/** Version that takes an existing spec def */
	FGameplayAbilitySpec(FGameplayAbilitySpecDef& InDef, int32 InGameplayEffectLevel, FActiveGameplayEffectHandle InGameplayEffectHandle = FActiveGameplayEffectHandle());

	/** Handle for outside sources to refer to this spec by */
	UPROPERTY()
	FGameplayAbilitySpecHandle Handle;
	
	/** Ability of the spec (Always the CDO. This should be const but too many things modify it currently) */
	UPROPERTY()
	TObjectPtr<UGameplayAbility> Ability;
	
	/** Level of Ability */
	UPROPERTY()
	int32	Level;

	/** InputID, if bound */
	UPROPERTY()
	int32	InputID;

	/** Object this ability was created from, can be an actor or static object. Useful to bind an ability to a gameplay object */
	UPROPERTY()
	TWeakObjectPtr<UObject> SourceObject;

	/** A count of the number of times this ability has been activated minus the number of times it has been ended. For instanced abilities this will be the number of currently active instances. Can't replicate until prediction accurately handles this.*/
	UPROPERTY(NotReplicated)
	uint8 ActiveCount;

	/** Is input currently pressed. Set to false when input is released */
	UPROPERTY(NotReplicated)
	uint8 InputPressed:1;

	/** If true, this ability should be removed as soon as it finishes executing */
	UPROPERTY(NotReplicated)
	uint8 RemoveAfterActivation:1;

	/** Pending removal due to scope lock */
	UPROPERTY(NotReplicated)
	uint8 PendingRemove:1;

	/** This ability should be activated once when it is granted. */
	UPROPERTY(NotReplicated)
	uint8 bActivateOnce : 1;

	/** Cached GameplayEventData if this ability was pending for add and activate due to scope lock */
	TSharedPtr<FGameplayEventData> GameplayEventData = nullptr;

	/** Activation state of this ability. This is not replicated since it needs to be overwritten locally on clients during prediction. */
	UPROPERTY(NotReplicated)
	FGameplayAbilityActivationInfo	ActivationInfo;

	/** Optional ability tags that are replicated.  These tags are also captured as source tags by applied gameplay effects. */
	UPROPERTY()
	FGameplayTagContainer DynamicAbilityTags;

	/** Non replicating instances of this ability. */
	UPROPERTY(NotReplicated)
	TArray<TObjectPtr<UGameplayAbility>> NonReplicatedInstances;

	/** Replicated instances of this ability.. */
	UPROPERTY()
	TArray<TObjectPtr<UGameplayAbility>> ReplicatedInstances;

	/**
	 * Handle to GE that granted us (usually invalid). FActiveGameplayEffectHandles are not synced across the network and this is valid only on Authority.
	 * If you need FGameplayAbilitySpec -> FActiveGameplayEffectHandle, then use AbilitySystemComponent::FindActiveGameplayEffectHandle.
	 */
	UPROPERTY(NotReplicated)
	FActiveGameplayEffectHandle	GameplayEffectHandle;

	/** Passed on SetByCaller magnitudes if this ability was granted by a GE */
	TMap<FGameplayTag, float> SetByCallerTagMagnitudes;

	/** Returns the primary instance, used for instance once abilities */
	UGameplayAbility* GetPrimaryInstance() const;

	/** interface function to see if the ability should replicated the ability spec or not */
	bool ShouldReplicateAbilitySpec() const;

	/** Returns all instances, which can include instance per execution abilities */
	TArray<UGameplayAbility*> GetAbilityInstances() const
	{
		TArray<UGameplayAbility*> Abilities;
		Abilities.Append(ReplicatedInstances);
		Abilities.Append(NonReplicatedInstances);
		return Abilities;
	}

	/** Returns true if this ability is active in any way */
	bool IsActive() const;

	void PreReplicatedRemove(const struct FGameplayAbilitySpecContainer& InArraySerializer);
	void PostReplicatedAdd(const struct FGameplayAbilitySpecContainer& InArraySerializer);

	FString GetDebugString();
};
  • GameplayAbility가 활성화 가능한 Ability가 정의된 후에 ASC에 존재하게 된다.
    • GameAbility Class
    • GameAbility Level
    • Input Binding
    • GameplayAbility Class로부터 분리되어야만 하는 runtime state
  • GameAbility가 Server에서 부여되면,
    Server는 해당 Ability의 GameplayAbilitySpec을 활성화 되어야 할 대상 Client에 Replicate 한다.
  • GameplayAbilitySpec을 활성화 하면 Instance Policy에 따라 GameplayAbility Instance가 생성된다.

Passing Data to Abilities

  • GameplayAbility의 범용적인 패러다임은 Activate -> General Data -> Aply -> End이다.
    • 하지만 때로는 이미 존재하는 Data를 기반으로 동작해야 하기도 하다.
  • GAS는 몇 가지 Gameplay Ability 외부의 데이터를 사용하는 옵션을 제공한다.

Activate GameplayAbility by Event

더보기
/**
 * This function can be used to trigger an ability on the actor in question with useful payload data.
 * NOTE: GetAbilitySystemComponent is called on the actor to find a good component, and if the component isn't
 * found, the event will not be sent.
 */
UFUNCTION(BlueprintCallable, Category = Ability, Meta = (Tooltip = "This function can be used to trigger an ability on the actor in question with useful payload data."))
static void SendGameplayEventToActor(AActor* Actor, FGameplayTag EventTag, FGameplayEventData Payload);
  • Payload가 있는 Data를 포함한 Event로 Gameplay Ability를 활성화
  • Event의 Payload는 Client에서 Server로 local predict 된 Gameplay Ability를 Replicate한다.
  • 다만 Ability를 Input Bind로 활성화 하는 것을 방지한다는 단점이 있다.

AbilityTask_WaitGameplayEvent 

  • Gameplay Ability가 활성화 된 후 Payload Data를 Event로 받도록 설정
  • Event Payload를 보내는 과정은 Gameplay Ability가 Event로 활성화 되는 것과 같다.
  • Event가 Ability Task로 REplicate 되지 않고, 오직 LocalOnly나 ServerOnly만 가능하다는 단점이 있다.

Use TargetData

  • Custom Target Data를 선언하여 Client와 Server 사이에 임시 Data 전달

Store Data on the OwnerActor or AvatarActor

  • OwnerActor나 AvatarActor, 혹은 Reference를 갖을 수 있는 Object의 Replicated Varaiable에 저장
  • 이 방법은 Input Bind로 활성화되는 Gameplay Ability로 작업하기에 가장 유연한 방법이다.
  • 하지만 Data를 사용하는 때에 Replication으로 동기화가 되었음을 보장할 수 없다.
    • Replicated Variable을 설정 한 직후 Gameplay Ability를 활성화 하는 경우에
      Packet loss로 인한 동기화 오류가 발생할 여지가 있다.

Ability Cost and Cooldown

  • Gameplay Ability는 선택적으로 Cost나 Cooldown 기능을 제공한다.
  • Cost
    • Instant GE로 실행할 때 반드시 충족해야 하는 ASC에서 사전에 선언된 Gameplay Ability가 Attribute의 요구량
  • Cooldown
    • Duration GE 가 만료된 이후 재실행 될 때까지 Gameplay Ability의 재실행을 방지하는 Duration
  • CanActivateAbility() 함수에서 해당 Gameplay Ability를 소유한 ASC에서 Cost와 Cooldown을 체크한다.
더보기
/** Checks cost. returns true if we can pay for the ability. False if not */
virtual bool CheckCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const;

/** Checks cooldown. returns true if we can be used again. False if not */
virtual bool CheckCooldown(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const;
  • Activate()가 호출된 후, 선택적으로 Cost와 Cooldown 관련 함수가 호출된다.
더보기
virtual bool CommitAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);
virtual bool CommitAbilityCooldown(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const bool ForceCooldown, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);
virtual bool CommitAbilityCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);

/** Applies CooldownGameplayEffect to the target */
virtual void ApplyCooldown(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) const;
/** Applies the ability's cost to the target */
virtual void ApplyCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) const;
  • Designer는 Cost와 Cooldown이 동시에 적용되지 않아야 하면 이를 분리할 수 있다.
  • 마지막으로 GameplayAbility는 Cost나 Cooldown으로 실행이 실패 했을 때 관련해서 한번 더 체크한다.
  • ASC의 Attribute는 GameplayAbility가 활성화 되면서 값이 변경되어 Cost 조건을 만족하지 못할 수도 있다.

Leveling Up Abilities

기존 Ability 부여를 해제하고 재부여

  • ASC에서 GameplayAbility를 제거
  • 다음 Level의 GameplayAbility를 Server에서 부여
  • 이 제거 동작은 활성화 될 때 발생한다.

GameplayAbilitySpec의 Level을 증가

  • Server에서 Level이 오르는 GameplayAbilitySpec을 탐색
  • 해당 GameplayAbilitySpec을 dirty 처리해서 Client에 Replicate 되도록 처리
  • GameplayAbility가 활성화 될 때 제거되지 않음

비교

  • Level이 상승할 때 해당 Gameplay Ability를 취소할 지 말지 정도의 차이가 있다.
  • 두가지 방법 모두 Gameplay Ability에 따라 매우 빈번하게 사용할 것이다.

Gameplay Ability Set

  • Input Bind와 초기 Gameplay Ability 정보를 담고 있는 편의성 Data Asset
    • Gameplay Ability를 부여하는 로직이 있는 캐릭터에게 유용
    • Subclass에서 외부 로직이나 Property를 포함시킬 수 있다.
    • Paragon에서는 영웅들이 소유하고 있는 고유한 Gameplay Ability를 들고 있는 Gameplay Ability Set을
      각각 가지고 있다.

Ability Batching

  • 전통적인 Gameplay Ability는 LifeCycle동안 Client에서 Server로 최소 2, 3개의 RPC를 보낸다.
    • CallServerTryActivateAbility()
    • ServerSetReplicatedTargetData()
      • 선택적
    • ServerEndAbility
  • 만약 위 모든 동작을 Frame에서 하나의 Atomic Group으로 수행할 수 있다면,
    모든 RPC를 하나의 RPC로 최적화 할 수 있다.
  • GAS는 이런 경우에 대해 Ability Batching 기능을 통해 RPC 최적화를 제공한다.
    • 대표적인 예시는 Hitscan 총기류이다.
    • Hitscan 총기류 활성화, Line Trace, Target Data를 서버로 전달을 한번에 처리한다.
  • 다만 Ability Batching은 ASC에서 Default로는 Disable 처리되어 있다.
    • 이를 사용하려면 아래 함수를 Override 해야 한다.
더보기
virtual bool ShouldDoServerAbilityRPCBatch() const { return false; }
  • Ability Batching을 활성화 하였다면, Batch 하고 싶은 Ability를 활성화 하기 전에
    FScopedServerAbilityRPCBatcher 구조체를 미리 만들어야 한다.
더보기
/** Helper struct for defining ServerRPC batch windows. If null ASC is passed in, this becomes a noop. */
struct GAMEPLAYABILITIES_API FScopedServerAbilityRPCBatcher
{
	FScopedServerAbilityRPCBatcher(UAbilitySystemComponent* InASC, FGameplayAbilitySpecHandle InAbilityHandle);
	~FScopedServerAbilityRPCBatcher();

private:

	UAbilitySystemComponent* ASC;
	FGameplayAbilitySpecHandle AbilityHandle;
	FScopedPredictionWindow ScopedPredictionWindow;
};
  • 이 구조체는 Scope 안의 Ability들을 모두 Batch한다.
    • 한 번 FScopedServerAbilityRPCBatcher의 Scope를 벗어나면, 활성화 된 어떠한 Ability들도 Batch 되지 않는다.
  • FScopedServerAbilityRPCBatcher는 RPC 호출을 가로채는 대신 구조체에 Batch 할 수 있는 message를 Batch 한다.
  • FScopedServerAbilityRPCBatcher의 Scope를 벗어날 때,
    UASC::EndServerAbilityRPCBatch() 함수를 통해 Batch 구조체를 Server로 RPC한다.
    • Server는 UASC::ServerAbilityRPCBatch_Internal 함수를 통해 Batch RPC를 받는다.
더보기
virtual void EndServerAbilityRPCBatch(FGameplayAbilitySpecHandle AbilityHandle);

// Overridable function for sub classes
virtual void ServerAbilityRPCBatch_Internal(FServerAbilityRPCBatch& BatchInfo);
  • 이 때 BatchInfo는 다음 Flag 정보를 포함한다.
    • Ability가 반드시 끝나야 하는지 여부
    • Activity가 활성화 되었을 때 Press Input이 발생했는지 여부
    • TargetData가 포함되었는지 여부
  • ServerAbilityRPCBatch_Internal은 Batch가 정상 동작하는지 확인하기 위해 Break Point를 걸기 매우 적절한 함수다.
  • 혹은 이를 대신 해, 아래 커맨드를 입력해 로그를 남길 수 있다.
더보기
AbilitySystem.ServerRPCBatching.Log 1
  • 다음은 Ability Batch에 대한 간단한 예시코드이다.
더보기
bool UGSAbilitySystemComponent::BatchRPCTryActivateAbility(FGameplayAbilitySpecHandle InAbilityHandle, bool EndAbilityImmediately)
{
	bool AbilityActivated = false;
	if (InAbilityHandle.IsValid())
	{
		FScopedServerAbilityRPCBatcher GSAbilityRPCBatcher(this, InAbilityHandle);
		AbilityActivated = TryActivateAbility(InAbilityHandle, true);

		if (EndAbilityImmediately)
		{
			FGameplayAbilitySpec* AbilitySpec = FindAbilitySpecFromHandle(InAbilityHandle);
			if (AbilitySpec)
			{
				UGSGameplayAbility* GSAbility = Cast<UGSGameplayAbility>(AbilitySpec->GetPrimaryInstance());
				GSAbility->ExternalEndAbility();
			}
		}

		return AbilityActivated;
	}

	return AbilityActivated;
}

Replication

  • 내부 상태 및 GE Replication을 지원
    • 이를 비활성화 하면 네트워크 대역폭과 CPU 사이클 절약이 가능

Gameplay Ability Replication Policy

  • Ability가 Network를 통해 자체 Instance를 Replicate 할지, 상태를 업데이트 할지, GE를 전송할지 제어하는 수단
  • 이름이 기능을 명확히 알려주지 않으며 사용하지 않는 것을 권장하는 옵션
    • GameplayAbilitySpec이 기본적으로 Server에서 Client로 Replicate된다.
    • 또한 GameplayAbility는 AbilityTask나 GameplayCue를 통해 Replicate 되거나 RPC를 호출한다.
    • 근시일에 이 기능을 제거할 것이라고 Epic의 Dave Ratti가 업급하기도 하였다.

Gameplay Net Execution Policy

  • Gameplay Ability가 로컬에서 predict 되는지 여부를 결정
  • GE의 추가 cost, cooldown과 관련된 기본적인 동작을 포함함.

Local Predicted

  • 반응성과 정확성 사이에 균현이 잘 잡힌 옵션
  • Client가 명령을 내리면 Local Client에서 Ability가 즉시 실행된다.
    • 하지만 실제 영향이 어땠는지에 대한 최종 결정은 Server가 내린다.
    • 그리고 이 값을 Client에 Override 할 수 있다.
  • 실제로 Client는 Server에 Ability 실행 권한을 요청하지만, Server가 동의할 것을 예상하고 Local로 진행한다.
  • Client는 Local에서 Ability의 Behaviour를 예측하므로
    서버와의 Behaviour가 다르지 않으면 지연 없이 매끄럽게 느껴진다.

Local Only

  • Client가 단순히 Local에서 Ability를 실행
  • Server에 Replicate하지 않는다.
    • Listen Server Host, Single Player Game에서는 서버에서도 실행되기도 한다.
    • Dedicate Server에서는 적용되지 않는다.
  • 이 Ability로 Client가 영향을 주는 모든 것은 일반 Replicate Protocol을 따른다.
    • 여기에 서버에서 보정을 받을 가능성도 포함된다.

Server Initiated

  • Server에서 시작하는 Abilit가 Client에 전파된다.
    • 종종 Client 관점에서 Server의 실제 상황과 더욱 정확하게 동작하기도 하지만,
      Ability를 사용하는 Client에서는 Delay가 관측된다.
    • Delay가 매우 짧더라도 긴박한 상황에서는 매끄럽지 않은 느낌을 받는다.

Server Only

  • Server에서만 Ability가 실행되고 Client로 Replicate 되지 않는다.
  • 이 Ability가 변경하는 모든 변수는 평소처럼 Replicate 된다.
    • Ability가 Server Authorized Data에 영향을 미칠 수 있고, 그 뒤에 Client에 Replicate 된다는 의미이다.
    • 이 방식을 통해 Ability를 Server에서만 실행 하더라도 Client가 관측하는 Effect를 계속 보유할 수 있다.

Net Security Policy

  • 대상 Ability가 Network 환경에서 어디서 실행되어야만 하는지 정의
  • Client에서 제한된 기능을 동작하는 것을 방지한다.

ClientOrServer

  • 아무런 보안이 필요 없음.
  • Server, Client 모두 자유롭게 실행과 제거를 할 수 있다.

ServerOnlyExecution

  • Client에서 이 Ability에 대한 실행 요청을 Server가 거부한다.
  • Client는 여전히 Server에 Ability의 취소나 종료 요청을 보낼 수는 있다.

ServerOnlyTermination

  • Client에서 이 Ability에 대한 취소/종료 요청을 Server가 거부한다.
  • Client는 여전히 Ability의 실행 요청을 보낼 수는 있다.

ServerOnly

  • 오직 Server에서만 Ability에 대한 실행과 제거를 조절한다.
  • Client에서 보내는 어떠한 요청도 모두 무시된다.

Server Respects Remote Ability Cancellation

  • Client의 GameplayAbility가 취소 혹은 정상적인 동작 종료로 끝난다면,
    서버에서 작업이 완수가 되었는지와 무관하게 강제로 끝낸다는 의미의 옵션
  • 특히 정상적인 종료의 케이스의 경우, Latency가 높은 유저의 경우 매우 중요한 문제를 야기할 수 있다.
  • 때문에 이 옵션도 사용하지 않는 것을 권장한다.

Replicate Input Directly

  • Client에서 발생하는 모든 Input Press/Release를 Server로 Replicate 하는 옵션
    • Epic에서는 이 옵션 사용을 지양하는 것을 권장한다.
    • 대신 ASC에 Input이 Bind 되어 있다면 기존 입력 관련해 Ability Task에서 제공하는
      Generic Replicated Event 사용을 권장한다.
더보기
/** Direct Input state replication. These will be called if bReplicateInputDirectly is true on the ability and is generally not a good thing to use. (Instead, prefer to use Generic Replicated Events). */
UFUNCTION(Server, reliable, WithValidation)
void ServerSetInputPressed(FGameplayAbilitySpecHandle AbilityHandle);

UFUNCTION(Server, reliable, WithValidation)
void ServerSetInputReleased(FGameplayAbilitySpecHandle AbilityHandle);

Instancing Policy

  • Gamplay Ability를 실행하면 보통 해당 Ability Type의 새 Object가 Spawn 되어 상황을 추적한다.
    • BR, MOBA, MMO, RTS 게임처럼 수백의 Player나 AI가 전투를 벌이는 경우,
      Ability 실행 빈도가 매우 높아져 Object 생성이 많아져 성능에 부정적인 영향을 줄 수 있다.
  • 이를 해결하기 위해 Ability에 3가지 Instancing Policy를 제공해 성능과 기능 사이 균형을 맞출 수 있다.

Instanced per Execution

  • Ability를 실행할 때마다 Ability Object의 사본을 Spawn

장점

  • BP Graph와 멤버 변수를 자유롭게 사용 할 수 있음
  • 실행 시작 시 모든 값이 Default로 초기화 된다.
  • 가장 간단하게 구현할 수 있는 Instancing Polity

단점

  • 대규모 Overhad가 수반되어 자주 실행되지 않는 Ability에 이상적
    • ex) MOBA의 궁극기

Instanced per Actor

  • Ability를 처음 실행하면 Actor마다 하나의 Ability Instance를 Spawn
    • 향후 재실행 시 해당 Instance를 재사용
  • Ability를 실행할 때마다 멤버 변수를 지워야 하지만, 여러번 실행에서 정보를 절약할 수 있다.
  • 각 Instance는 Ability에 Replicated Object를 통해 변수 변화와 RPC를 처리 할 수 있다.
    • 하지만 실행할 때마다 새 Object를 Spawn하느라 네트워크 대역폭과 CPU 시간이 낭비되지 않는다.
    • 때문에 Replication에 이상적이다.
  • 규모가 큰 상황에서 Performance가 뛰어난 정책
    • 많은 수의 Actor가 처음 Ability를 사용할 때에만 Object를 Spawn하기 때문

Non-Instanced

  • 전체 Category 중 가장 효율적인 Instancing Policy
  • Ability를 실행할 때마다 Object Spawn 대신 Class Default Object를 사용
  • 하지만 이런 효용성으로 인해 몇 가지 제약사항이 발생한다.
    • C++로만 작성이 가능하다.
    • Instance가 없는 Ability의 BP Class를 생성할 수는 있지만,
      노출된 Property의 Default 값을 변경할 때에만 사용 가능하다.
    • Ability는 실행 중에 멤버 변수를 변경하거나 Delegate Bind를 하면 안된다.
    • 변수를 Replicate 하거나 RPC를 처리할 수 없다.
  • 내부적인 변수 저장과 Data Replication이 필요 없는 Ability에만 사용
    • 다만 Ability의 사용자가 Attribute를 설정하는 것은 가능
  • ex) RTS나 MOBA 게임에서 유닛이 사용하는 기본 공격

Trigger with Gameplay Event

  • 일반 Channel을 통하지않고도 어떤 Context의 Data Payload를 전송해
    Ability를 직접 Trigger 하도록 전달될 수 있는 Struct
  • 일반적으로 다음 기능을 제공
    • Actor에 SendGameplayEventToActor을 호출
    • IAbilitySystmInterface와 Gameplay Event에 필요한 Context 정보를 구현하는 Actor 제공
  • 하지만 ASC에서 HandleGameplayEvent를 바로 호출해도 문제 없다.
  • Gameplay Ability를 호출하는 정상적인 경로가 아니기에
    필요한 Context 정보는 FGameplayEventData 구조체로 전달한다.
  • 이 구조체는 범용이기 때문에 특정 Gameplay Event나 Ability용으로 확장되지 않는다.
    • 하지만 ContextHandle 관련 필드에 부가 정보를 제공하면 Ability나 Gameplay Event용으로 사용할 수 있다.
  • Gameplay Event가 Gameplay Ability를 Trigger하면, Activate Ability 대신 Activate Ability From Event를 사용한다.
    • Activate Ability From Event는 부가 Context Data를 parameter로 제공할 수 있다.
  • Ability가 Gameplay Event에 반응하려면 반드시 Activate Ability from Event로 처리되어야 한다.
    • 하지만 BP에서 구현되고 나면 Activate Ability를 대신해 모든 Acitivate Traffic을 받게 된다.

'UE5 > GAS' 카테고리의 다른 글

[GAS] Prediction  (0) 2024.05.21
[GAS] Gameplay Cue  (0) 2024.05.21
[GAS] Ability Task  (0) 2024.05.16
[GAS] Gameplay Effect  (0) 2024.05.15
[GAS] Attribute Set  (1) 2024.05.14

+ Recent posts