언리얼 라이라 프로젝트와 엮어서 Gameplay Ability Sytem을 전체적으로 정리해봤다.
// UAbilitySystemComponent class
/** Full list of all instance-per-execution gameplay abilities associated with this component */
UE_DEPRECATED(5.1, "This array will be made private. Use GetReplicatedInstancedAbilities, AddReplicatedInstancedAbility or RemoveReplicatedInstancedAbility instead.")
UPROPERTY()
TArray<TObjectPtr<UGameplayAbility>> AllReplicatedInstancedAbilities;
// UAbilitySystemComponent class
/** List of attribute sets */
UPROPERTY(Replicated, ReplicatedUsing = OnRep_SpawnedAttributes, Transient)
TArray<TObjectPtr<UAttributeSet>> SpawnedAttributes;

게임 플레이 어빌리티 시스템은 플러그인으로 제공된다.
PublicDependencyModuleNames.AddRange(new string[] { "GameplayAbilities", "GameplayTags", "GameplayTasks", "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay" });
플러그인 활성화 후 Build.cs > PublicDependencyModuleNames에 'GameplayAbilities', 'GameplayTags', 'GameplayTasks'를 추가한다.
UCLASS(Config = Game)
class LYRAGAME_API ALyraPlayerState : public AModularPlayerState, public IAbilitySystemInterface, public ILyraTeamAgentInterface
{
// ...
// The ability system component sub-object used by player characters.
UPROPERTY(VisibleAnywhere, Category = "Lyra|PlayerState")
TObjectPtr<ULyraAbilitySystemComponent> AbilitySystemComponent;
// ...
};
ULyraAbilitySystemComponent를 소유함으로써 기본 폰 데이터와 GAS 스테이트 로직을 분리할 수 있다.
UCLASS(Config = Game)
class LYRAGAME_API ALyraGameState : public AModularGameStateBase, public IAbilitySystemInterface
{
// The ability system component subobject for game-wide things (primarily gameplay cues)
UPROPERTY(VisibleAnywhere, Category = "Lyra|GameState")
TObjectPtr<ULyraAbilitySystemComponent> AbilitySystemComponent;
};
마찬가지로 ALyraGameState도 ULyraAbilitySystemComponent를 통해 게임페이즈를 관리힌다.
ULyraAbilitySystemComponent는 초기화 중에 자동으로 ULyraGlobalAbilitySystem 등록된다.
따라서 레벨의 모든 ULyraAbilitySystemComponent를 추적하고 상호작용할 수 있습니다.
등록된 어빌리티 시스템 컴포넌트들에 어빌리티와 게임플레이 이펙트를 제거하거나 부여하는 블루프린트 호출 가능 함수를 제공한다.
UCLASS()
class ULyraGlobalAbilitySystem : public UWorldSubsystem
{
GENERATED_BODY()
public:
ULyraGlobalAbilitySystem();
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="Lyra")
void ApplyAbilityToAll(TSubclassOf<UGameplayAbility> Ability);
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="Lyra")
void ApplyEffectToAll(TSubclassOf<UGameplayEffect> Effect);
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Lyra")
void RemoveAbilityFromAll(TSubclassOf<UGameplayAbility> Ability);
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Lyra")
void RemoveEffectFromAll(TSubclassOf<UGameplayEffect> Effect);
/** Register an ASC with global system and apply any active global effects/abilities. */
void RegisterASC(ULyraAbilitySystemComponent* ASC);
/** Removes an ASC from the global system, along with any active global effects/abilities. */
void UnregisterASC(ULyraAbilitySystemComponent* ASC);
private:
UPROPERTY()
TMap<TSubclassOf<UGameplayAbility>, FGlobalAppliedAbilityList> AppliedAbilities;
UPROPERTY()
TMap<TSubclassOf<UGameplayEffect>, FGlobalAppliedEffectList> AppliedEffects;
UPROPERTY()
TArray<TObjectPtr<ULyraAbilitySystemComponent>> RegisteredASCs;
};
// 등록된 어빌리티 시스템 컴포넌트들에 게임플레이 이펙트를 부여
void ULyraGlobalAbilitySystem::ApplyEffectToAll(TSubclassOf<UGameplayEffect> Effect)
{
if ((Effect.Get() != nullptr) && (!AppliedEffects.Contains(Effect)))
{
FGlobalAppliedEffectList& Entry = AppliedEffects.Add(Effect);
for (ULyraAbilitySystemComponent* ASC : RegisteredASCs)
{
Entry.AddToASC(Effect, ASC);
}
}
}
// actor 초기화할 때 ULyraGlobalAbilitySystem에 컴포넌트 등록
void ULyraAbilitySystemComponent::InitAbilityActorInfo(AActor* InOwnerActor, AActor* InAvatarActor)
{
// ...
// Register with the global system once we actually have a pawn avatar. We wait until this time since some globally-applied effects may require an avatar.
if (ULyraGlobalAbilitySystem* GlobalAbilitySystem = UWorld::GetSubsystem<ULyraGlobalAbilitySystem>(GetWorld()))
{
GlobalAbilitySystem->RegisterASC(this);
}
// ...
}
// 월드에서 제거되면 ULyraGlobalAbilitySystem에서도 제거
void ULyraAbilitySystemComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
if (ULyraGlobalAbilitySystem* GlobalAbilitySystem = UWorld::GetSubsystem<ULyraGlobalAbilitySystem>(GetWorld()))
{
GlobalAbilitySystem->UnregisterASC(this);
}
Super::EndPlay(EndPlayReason);
}
데이터 에셋 유형으로 라이라 캐릭터에게 부여할 게임플레이 어빌리티, 게임플레이 이펙트, 어트리뷰트 세트 목록을 갖고 있다.
/**
* ULyraAbilitySet
*
* Non-mutable data asset used to grant gameplay abilities and gameplay effects.
*/
UCLASS(BlueprintType, Const)
class ULyraAbilitySet : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
ULyraAbilitySet(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
// Grants the ability set to the specified ability system component.
// The returned handles can be used later to take away anything that was granted.
void GiveToAbilitySystem(ULyraAbilitySystemComponent* LyraASC, FLyraAbilitySet_GrantedHandles* OutGrantedHandles, UObject* SourceObject = nullptr) const;
protected:
// Gameplay abilities to grant when this ability set is granted.
UPROPERTY(EditDefaultsOnly, Category = "Gameplay Abilities", meta=(TitleProperty=Ability))
TArray<FLyraAbilitySet_GameplayAbility> GrantedGameplayAbilities;
// Gameplay effects to grant when this ability set is granted.
UPROPERTY(EditDefaultsOnly, Category = "Gameplay Effects", meta=(TitleProperty=GameplayEffect))
TArray<FLyraAbilitySet_GameplayEffect> GrantedGameplayEffects;
// Attribute sets to grant when this ability set is granted.
UPROPERTY(EditDefaultsOnly, Category = "Attribute Sets", meta=(TitleProperty=AttributeSet))
TArray<FLyraAbilitySet_AttributeSet> GrantedAttributes;
};
// Actor가 가지고 있는 ULyraAbilitySystemComponent에 어빌리티 세트를 적용
void ALyraPlayerState::SetPawnData(const ULyraPawnData* InPawnData)
{
//...
for (const ULyraAbilitySet* AbilitySet : PawnData->AbilitySets)
{
if (AbilitySet)
{
AbilitySet->GiveToAbilitySystem(AbilitySystemComponent, nullptr);
}
}
// ...
}
FGameplayEffectContext 구조체에서 확장되어 Gameplay Cue Notifies 에 전송할 추가 데이터 멤버와 함수를 정의한다.
여기서 GameplayCueNotify는 시각 이펙트나 사운드와 같은 게임 로직과 무관한 시각적, 청각적 기능을 담당하는 클래스를 말한다.
언리얼5_4_3 : 게임플레이 어빌리티 시스템의 활용 방법
UAttributeSet 클래스를 상속받은 클래스로 게임플레이 어트리뷰트 프로퍼티를 자동화하기 위한 편리한 ATTRIBUTE_ACCESSORS 매크로를 제공한다.
/**
* This macro defines a set of helper functions for accessing and initializing attributes.
*
* The following example of the macro:
* ATTRIBUTE_ACCESSORS(ULyraHealthSet, Health)
* will create the following functions:
* static FGameplayAttribute GetHealthAttribute();
* float GetHealth() const;
* void SetHealth(float NewVal);
* void InitHealth(float NewVal);
*/
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
/**
* Delegate used to broadcast attribute events, some of these parameters may be null on clients:
* @param EffectInstigator The original instigating actor for this event
* @param EffectCauser The physical actor that caused the change
* @param EffectSpec The full effect spec for this change
* @param EffectMagnitude The raw magnitude, this is before clamping
* @param OldValue The value of the attribute before it was changed
* @param NewValue The value after it was changed
*/
DECLARE_MULTICAST_DELEGATE_SixParams(FLyraAttributeEvent, AActor* /*EffectInstigator*/, AActor* /*EffectCauser*/, const FGameplayEffectSpec* /*EffectSpec*/, float /*EffectMagnitude*/, float /*OldValue*/, float /*NewValue*/);
/**
* ULyraAttributeSet
*
* Base attribute set class for the project.
*/
UCLASS()
class LYRAGAME_API ULyraAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
ULyraAttributeSet();
UWorld* GetWorld() const override;
ULyraAbilitySystemComponent* GetLyraAbilitySystemComponent() const;
};
UCLASS(BlueprintType)
class ULyraHealthSet : public ULyraAttributeSet
{
GENERATED_BODY()
public:
ULyraHealthSet();
// ULyraAttributeSet에서 정의한 매크로 사용
ATTRIBUTE_ACCESSORS(ULyraHealthSet, Health);
ATTRIBUTE_ACCESSORS(ULyraHealthSet, MaxHealth);
ATTRIBUTE_ACCESSORS(ULyraHealthSet, Healing);
ATTRIBUTE_ACCESSORS(ULyraHealthSet, Damage);
// ...
};
UCLASS(BlueprintType)
class ULyraCombatSet : public ULyraAttributeSet
{
GENERATED_BODY()
public:
ULyraCombatSet();
ATTRIBUTE_ACCESSORS(ULyraCombatSet, BaseDamage);
ATTRIBUTE_ACCESSORS(ULyraCombatSet, BaseHeal);
// ...
};
언리얼 엔진의 게임플레이 어빌리티 시스템 | 언리얼 엔진 5.5 문서 | Epic Developer Community | Epic Developer Community
언리얼 엔진에서 라이라의 어빌리티 | 언리얼 엔진 5.5 문서 | Epic Developer Community | Epic Developer Community