언리얼 엔진의 게임플레이 어빌리티 시스템 컴포넌트 및 게임플레이 어트리뷰트를 살펴봅니다.
게임플레이 어트리뷰트 및 어트리뷰트 세트와 함께 어빌리티 시스템 컴포넌트를 사용하는 방법을 살펴봅니다.
dev.epicgames.com
- UGameAbilitySystemComponent는 Actor와 GAS 사이의 가교 역할을 한다.
- GAS와 상호작용해야 하는 Actor는 다음 2가지 조건 중 하나를 반드시 만족해야 한다.
- Ability System Component(이하 ASC)를 가지고 있거나
- 다른 Actor의 ASC에 Access 할 수 있거나.
- ASC는 FGameplayAbilitySpecContainer ActivatableAbilities 중 승인된 Gameplay Abilities를 가지고 있다.
- 언제나 ActivatableAbilities.Items를 통해 iterate를 하려 한다면,
List의 변화를 막기 위해 ABILITY_SCOPE_LOCK()을 반복문 앞에 추가해 Lock을 걸어야 한다. - 매 ABILITY_SCOPE_LOCK() 호출 범위마다 AbilityScopeLockCount가 증가하고,
그 범위를 벗어나면 AbilityScopeLockCount가 감소한다. - ABILITY_SCOPE_LOCK() 호출 범위 내에서 Ability를 제거하지 말 것.
- List가 Lock이 걸려 있으면 AbilityScopeLockCount를 확인하여 제거를 방지한다.
기본 요구사항
- Actor가 Game Ability System를 사용하려면 다음 2가지를 충족해야 한다.
- IAbilitySystemInterface 구현
- GetAbilitySystemComponent 함수 override
- Actor가 자체 ASC를 가지고 있는 것이 일반적이다.
- 하지만 다른 Actor가 소유한 ASC를 사용하려는 경우가 있다.
- Player의 Pawn/Character가 소환/소멸 되거나 처리할 때 리셋되면 안되는 것들이 포함되어 있기 때문.
Replication Mode
- ASC는 GameplayEffects, GameplayTags, GameplayCues에 대해 3가지 Replication Mode를 제공한다.
- Attributes는 속한 AttributeSet에 의해 Replicate된다.
Full
- Single Player에서 사용
- 모든 GameplayEffects가 모든 Client에 Replicate된다.
Mixed
- Multiplayer에서 유저가 Control 하는 Actor
- GameplayEffects가 소유한 Client에게만 Replicate된다.
- GameplayTags와 GameplayCues만 모두에게 Replicate된다.
Advanced
- 이 Mode에서 OwnerActor의 Owner가 Controller가 되는 것을 권장한다.
- PlayerState의 Parent는 기본적으로 Controller이지만, Character는 그렇지 않다.
- OwnerActor가 PlayerState가 아닌 상태에서 Mixed Mode를 사용하는 경우,
SetOwner() 함수를 호출해 OwnerActor를 Controller로 명시해야 한다. - 4.24 버전 이후(현재)에는 PossessedBy() 함수로 Owner를 Controller로 지정한다.
Minimal
- Multiplayer에서 AI가 Control 하는 Actor
- GameplayEffects가 어디에도 Replicate 되지 않는다.
- GameplayTags와 GameplayCues만 모두에게 Replicate 된다.
예시
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
ASC가 Actor에 있는 경우
-
더보기
AGDPlayerState::AGDPlayerState() { // Create ability system component, and set it to be explicitly replicated AbilitySystemComponent = CreateDefaultSubobject<UGDAbilitySystemComponent>(TEXT("AbilitySystemComponent")); AbilitySystemComponent->SetIsReplicated(true); //... }
class APACharacterBase : public AActor, public IAbilitySystemInterface { //~ IAbilitySystemInterface 시작 /** 어빌리티 시스템 컴포넌트를 반환합니다. */ virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override; //~ IAbilitySystemInterface 끝 /** 어빌리티 시스템 컴포넌트입니다. 게임플레이 어트리뷰트 및 게임플레이 어빌리티를 사용하려면 필요합니다. */ UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "Abilities") UAbilitySystemComponent* AbilitySystemComponent; }
void APACharacterBase::PossessedBy(AController * NewController) { Super::PossessedBy(NewController); if (AbilitySystemComponent) { AbilitySystemComponent->InitAbilityActorInfo(this, this); } // ASC MixedMode replication requires that the ASC Owner's Owner be the Controller. SetOwner(NewController); } UAbilitySystemComponent* APACharacterBase::GetAbilitySystemComponent() const { return AbilitySystemComponent; }
void APAPlayerControllerBase::AcknowledgePossession(APawn* P) { Super::AcknowledgePossession(P); APACharacterBase* CharacterBase = Cast<APACharacterBase>(P); if (CharacterBase) { CharacterBase->GetAbilitySystemComponent()->InitAbilityActorInfo(CharacterBase, CharacterBase); } //... }
- ASC는 Server, Client 양쪽에서 모두 Initialize되어야 한다.
- 또한 Controller가 Set(Possess)되고 나서 Initialize 되기를 원한다.
- SinglePlay는 Server 파트에 대해서만 걱정을 하면 된다.
- ASC가 설정된 Player는 각 파트에서 명시적으로 함수를 호출하여 Initialize를 해야 한다.
- Server 파트: Pawn::PossessedBy()
- Client 파트: APlayerController::AcknoledgePossession
- ASC는 Server, Client 양쪽에서 모두 Initialize되어야 한다.
고급 시나리오
- 다른 Actor가 소유한 ASC를 사용하는 Actor를 구성할 수 있다.
- ex) UPlayerState가 소유한 ASC를 사용하는 Pawn
- 이를 위해 GetAbilitySystemComponent 함수가 Owner에서 ASC를 얻거나, 캐싱해야 한다.
- 이 방식은 다음 속성이 있는 프로젝트에서 주로 발생한다.
- Player가 제어하는 Actor가 리스폰을 하고, 그 과정에서 Game Ability System 정보가 필요한 경우
- 장비나 Modular Machine, 신체 부위를 표현하기 위해 Actor가 자신에게 다른 Actor를 Attach하는 경우
- 간단한 AI나 MOBA 게임
- Attach 된 Actor의 Gameplay Ability System Interaction은 Parent의 ASC에 라우팅 할 수 있다.
- 가장 간단하게 구현하는 방법은 Attach된 Actor의 GetAbilitySystemComponent가 Parent로 전달되는 것.
- Actor 다른 ACtor에 Attach되거나 처리되는 동안 Cache 된 Pointer를 유지하면 Performance를 향상할 수 있다.
- 단, ASC가 PlayerState에 있는 경우, PlayerState의 NetUpdateFrequency를 늘려야 한다.
- PlayerState의 NetUpdateFrequency 기본값이 매우 낮음으로 되어 있기 때문에 딜레이나 랙을 유발할 수 있다.
- Adaptive network Updat Frequency를 활성화 하는 것을 권장.
- Gameplay Ability System은 다수의 Actor가 하나의 Ability System Component를 공유하는 것은 지원한다.
- 하지만 하나의 Actor가 다수의 Ability System Component를 가지는 것은 지원하지 않는다.
- Actor의 Ability system Component에 변경사항을 적용하고 이를 얻을 때 모호함을 유발할 수 있기 때문.
Replicate Actor Properties In Unreal Engine | Unreal Engine 5.4 Documentation | Epic Developer Community
Learn how to replicate actor properties in Unreal Engine; including conditional replication, custom conditions, and object references.
dev.epicgames.com
ASC가 PlayerState에 있는 경우
-
더보기
// Server only void AGDHeroCharacter::PossessedBy(AController * NewController) { Super::PossessedBy(NewController); AGDPlayerState* PS = GetPlayerState<AGDPlayerState>(); if (PS) { // Set the ASC on the Server. Clients do this in OnRep_PlayerState() AbilitySystemComponent = Cast<UGDAbilitySystemComponent>(PS->GetAbilitySystemComponent()); // AI won't have PlayerControllers so we can init again here just to be sure. No harm in initing twice for heroes that have PlayerControllers. PS->GetAbilitySystemComponent()->InitAbilityActorInfo(PS, this); } //... }
// Client only void AGDHeroCharacter::OnRep_PlayerState() { Super::OnRep_PlayerState(); AGDPlayerState* PS = GetPlayerState<AGDPlayerState>(); if (PS) { // Set the ASC for clients. Server does this in PossessedBy. AbilitySystemComponent = Cast<UGDAbilitySystemComponent>(PS->GetAbilitySystemComponent()); // Init ASC Actor Info for clients. Server will init its ASC when it possesses a new Actor. AbilitySystemComponent->InitAbilityActorInfo(PS, this); } // ... }
- ASC가 PlayerState에 있는 경우에는 명시적으로 Initialize 하는데 호출되는 함수가 달라진다.
- Server: Pawn::PossessedBy()
- Client: Pawn::Onrep_PlayerState()
- 이 모든 과정은 Client에 PlayerState가 있다는 것을 상정하고 작업된다.
- 만약 아래 로그가 발생하면, ASC가 Client에서 Initialize가 되지 않은 것이다.
- LogAbilitySystem: Warning: Can't activate LocalOnly or LocalPredicted ability %s when not local!
- ASC가 PlayerState에 있는 경우에는 명시적으로 Initialize 하는데 호출되는 함수가 달라진다.
'UE5 > GAS' 카테고리의 다른 글
[GAS] Ability Task (0) | 2024.05.16 |
---|---|
[GAS] Gameplay Effect (0) | 2024.05.15 |
[GAS] Attribute Set (1) | 2024.05.14 |
[GAS] Gameplay Attribute (0) | 2024.05.13 |
[GAS] Gameplay Ability System 소개 (0) | 2024.05.10 |