ASC 내부 구조
AbilitySystemComponent의 핵심 컨테이너와 데이터 흐름
AbilitySystemComponent 핵심 역할
GAS의 심장, 모든 상호작용의 중앙 허브
AbilitySystemComponent(ASC)는 UActorComponent를 상속받아 GAS의 모든 기능을 관리합니다. 어빌리티 부여/활성화, GameplayEffect 적용, GameplayTag 관리, 네트워크 복제까지 모든 시스템 상호작용의 중심입니다.
- 어빌리티 관리 - 부여, 활성화, 취소, 제거
- GameplayEffect 관리 - 적용, 스택, 제거, Duration 추적
- Attribute 관리 - AttributeSet 소유, 값 변경 처리
- GameplayTag 관리 - 태그 추가/제거, 카운트 추적
- 네트워크 복제 - 예측, 롤백, 동기화
핵심 컨테이너
ASC 내부의 주요 데이터 구조
// AbilitySystemComponent의 주요 내부 구조
class UAbilitySystemComponent : public UActorComponent
{
// 현재 활성화된 GameplayEffect들을 저장
FActiveGameplayEffectsContainer ActiveGameplayEffects;
// 부여된 어빌리티들을 저장
FGameplayAbilitySpecContainer ActivatableAbilities;
// GameplayTag 관리 (태그별 카운트)
FGameplayTagCountContainer GameplayTagCountContainer;
// 예측 키 관리 (네트워크 예측용)
FReplicatedPredictionKeyMap ReplicatedPredictionKeyMap;
};
ActiveGameplayEffects
현재 적용 중인 모든 GameplayEffect 인스턴스를 저장합니다. Duration, Stacking, Periodic 처리를 담당합니다.
ActivatableAbilities
부여된 어빌리티의 FGameplayAbilitySpec 배열입니다. 각 Spec은 어빌리티 클래스, 레벨, 입력 바인딩 정보를 포함합니다.
GameplayTagCountContainer
각 태그의 활성 카운트를 추적합니다. 동일 태그가 여러 소스에서 적용될 때 참조 카운팅을 사용합니다.
ReplicatedPredictionKeyMap
클라이언트 예측에서 생성된 키를 서버와 동기화합니다. 롤백 판단에 사용됩니다.
Owner와 Avatar 구분
ASC의 논리적 소유자와 물리적 표현
| 개념 | 설명 | 예시 |
|---|---|---|
| OwnerActor | ASC가 실제로 붙어있는 Actor | PlayerState (Lyra/Fortnite 방식) |
| AvatarActor | 물리적 표현, 게임 월드에서 보이는 Actor | Character Pawn |
// 캐릭터에서 ASC 접근을 위한 인터페이스 구현
class AMyCharacter : public ACharacter, public IAbilitySystemInterface
{
public:
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override
{
return AbilitySystemComponent;
}
private:
UPROPERTY()
UAbilitySystemComponent* AbilitySystemComponent;
};
Pawn이 Respawn되어도 PlayerState의 ASC는 유지됩니다. 버프/쿨다운 상태가 캐릭터 교체 후에도 지속됩니다. Lyra와 Fortnite에서 사용하는 권장 패턴입니다.
ASC 초기화 패턴
서버와 클라이언트에서의 초기화 시점
// PlayerState에서 ASC 생성
void AMyPlayerState::BeginPlay()
{
Super::BeginPlay();
if (AbilitySystemComponent)
{
// OwnerActor = this (PlayerState)
// AvatarActor = GetPawn() (Character)
AbilitySystemComponent->InitAbilityActorInfo(this, GetPawn());
}
}
// 서버: Pawn이 Possess될 때
void AMyCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
if (AMyPlayerState* PS = GetPlayerState<AMyPlayerState>())
{
AbilitySystemComponent = PS->GetAbilitySystemComponent();
AbilitySystemComponent->InitAbilityActorInfo(PS, this);
}
}
// 클라이언트: PlayerState가 복제된 후
void AMyCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
if (AMyPlayerState* PS = GetPlayerState<AMyPlayerState>())
{
AbilitySystemComponent = PS->GetAbilitySystemComponent();
AbilitySystemComponent->InitAbilityActorInfo(PS, this);
}
}
InitAbilityActorInfo()는 반드시 ASC가 생성된 후, 그리고 Owner/Avatar가 유효한 시점에 호출해야 합니다. 클라이언트에서는 복제 순서에 따라 OnRep_PlayerState()에서 호출하는 것이 안전합니다.
데이터 흐름 다이어그램
ASC를 중심으로 한 GAS 컴포넌트 관계
[AbilitySystemComponent]
|
+---------------------+---------------------+
| | |
[AttributeSet] [GameplayAbility] [GameplayTags]
| | |
v v v
Health, Mana... Skills, Actions State Flags
^ |
| v
+--------[GameplayEffect]---------+
| |
v v
Instant/Duration Modifiers
버프, 디버프 데미지 계산
- GameplayAbility -> GameplayEffect: 어빌리티가 이펙트를 적용
- GameplayEffect -> AttributeSet: 이펙트가 어트리뷰트 수정
- GameplayEffect -> GameplayTags: 이펙트가 태그 부여/제거
- GameplayTags -> GameplayAbility: 태그가 어빌리티 활성화 조건에 영향
핵심 요약
- ASC는 GAS의 중앙 허브로 어빌리티, 이펙트, 태그, 어트리뷰트를 관리
- 핵심 컨테이너: ActiveGameplayEffects, ActivatableAbilities, GameplayTagCountContainer
- OwnerActor는 ASC의 논리적 소유자, AvatarActor는 물리적 표현
- PlayerState 소유 패턴에서 Pawn 교체 시에도 버프/쿨다운 상태 유지
- IAbilitySystemInterface 구현으로 ASC 접근 표준화
도전 과제
배운 내용을 직접 실습해보세요
UAbilitySystemComponent를 커스텀 Character에 추가하고, InitAbilityActorInfo()를 PossessedBy(서버)와 OnRep_PlayerState(클라이언트)에서 각각 호출하세요. GiveAbility()로 기본 어빌리티를 부여하세요.
ASC를 Character에 직접 두는 방식과 PlayerState에 두는 방식을 각각 구현하고, 캐릭터 리스폰 시 어빌리티 유지 여부를 비교하세요.
undefined