어빌리티 시스템 컴포넌트(ASC, Ability System Component)
게임플레이 어빌리티 및 다양한 작업을 관리하고 처리하는 중앙 처리 장치
액터에 단 하나만 부착할 수 있고, 게임플레이 어빌리티를 발동시킬 수 있음
ASC를 부착한 액터 사이에 GAS 시스템의 상호작용이 가능
게임플레이 어빌리티(GA, GamePlay Ability)
ASC에 등록되어 발동시킬 수 있는 액션(공격, 마법 등 간단한 액션 뿐만아니라 복잡한 액션) 명령
GA의 발동 과정
- ASC에 어빌리티를 등록 : ASC의 GiveAbility 함수에 발동할 GA의 타입을 전달
발동할 GA 타입 정보를 게임플레이 어빌리티 스펙이라고 함 - ASC에게 어빌리티를 발동하려고 명령 : ASC의 TryActivateAbility 함수에 발동할 GA의 타입을 전달
ASC에 등록된 타입이면 GA의 인스턴스가 생성됨 - 발동된 GA에는 발동한 액터와 실행정보가 기록됨
SpecHandle : 발동된 어빌리티에 대한 핸들
ActorInfo : 어빌리티 소유자와 아바타(비주얼만 수행하는 액터) 정보
ActivationInfo : 발동 방식에 대한 정보
GA의 주요 함수
CanActivateAbility : 어빌리티가 발동할 수 있는지 체크하는 함수
ActivateAbility : 어빌리티가 발동될 때 호출
CancelAbility : 어빌리티가 취소될 때 호출
EndAbility : 스스로 어빌리티를 마무리할 때 호출
AABGASFountain::AABGASFountain()
{
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
RotatingMovement = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("RotateMovement"));
ActionPeriod = 3.0f;
}
void AABGASFountain::PostInitializeComponents()
{
Super::PostInitializeComponents();
// 액터가 초기화될 때 반드시 InitAbilityActorInfo 함수를 호출하여 AbilitySystemComponent를 초기화해야 함
AbilitySystemComponent->InitAbilityActorInfo(this, this);
// 처음부터 인스턴스를 생성하면 부하가 클 수 있기 때문에 기본적인 정보만 보유
FGameplayAbilitySpec RotateSkillSpec(UABGA_Rotate::StaticClass());
AbilitySystemComponent->GiveAbility(RotateSkillSpec);
RotatingMovement->bAutoActivate = false;
RotatingMovement->Deactivate();
}
void AABGASFountain::BeginPlay()
{
Super::BeginPlay();
GetWorld()->GetTimerManager().SetTimer(ActionTimer, this, &AABGASFountain::TimerAction, ActionPeriod, true, 0.0f);
}
void AABGASFountain::TimerAction()
{
ABGAS_LOG(LogABGAS, Log, TEXT("Begin"));
FGameplayAbilitySpec* RotateSpec = AbilitySystemComponent->FindAbilitySpecFromClass(UABGA_Rotate::StaticClass());
if (RotateSpec == nullptr)
{
ABGAS_LOG(LogABGAS, Log, TEXT("Rotate Spec Not Found"));
return;
}
if (RotateSpec->IsActive() == false)
{
AbilitySystemComponent->TryActivateAbility(RotateSpec->Handle);
}
else
{
AbilitySystemComponent->CancelAbilityHandle(RotateSpec->Handle);
}
}
void UABGA_Rotate::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
if (AActor* AvatarActor = ActorInfo->AvatarActor.Get())
{
if (UActorComponent* RotatingMovement = AvatarActor->GetComponentByClass(URotatingMovementComponent::StaticClass()))
{
RotatingMovement->Activate(true);
}
}
}
void UABGA_Rotate::CancelAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateCancelAbility)
{
Super::CancelAbility(Handle, ActorInfo, ActivationInfo, bReplicateCancelAbility);
if (AActor* AvatarActor = ActorInfo->AvatarActor.Get())
{
if (UActorComponent* RotatingMovement = AvatarActor->GetComponentByClass(URotatingMovementComponent::StaticClass()))
{
RotatingMovement->Deactivate();
}
}
}
게임플레이 태그
FName으로 관리되는 경량의 표식 데이터(액터나 컴포넌트에 지정했던 태그와는 다름)
프로젝트 설정에서 별도로 게임플레이 태그를 생성하고 관리할 수 있음
결과는 DefaultGamePlayTags.ini 파일에 저장됨
계층 구조로 구성되어 있어 체계적인 관리 가능
Actor.Action.Rotate : 행동에 대한 태그
Actor.State.IsRotating : 상태에 대한 태그
게임플레이 태그들의 저장소 : GamePlayTagContainer
계층구조를 지원하는 검색 기능 제공
HasTagExact : 완전히 일치하는지 체크 : 컨테이너에 A.1 태그가 있는 상황에서 A로 찾으면 false
HasAny : 컨테이너에 A.1 태그가 있는 상황에서 A와 B로 찾으면 true
HasAnyExact : 컨테이너에 A.1 태그가 있는 상황에서 A와 B로 찾으면 false
HasAll : 컨테이너에 A.1, B.1 태그가 있는 상황에서 A와 B로 찾으면 true
HasAllExact : 컨테이너 A.1, B.1 태그가 있는 상황에서 A와 B로 찾으면 false
GAS와 독립적으로 사용 가능
게임플레이 어빌리티에 부착한 태그
TagContainer에 Tag를 부착하면 게임플레이 어빌리티를 대표하는 태그가 됨
게임플레이 어빌리티에 대한 다양한 실행 조건의 설정
태그로 어빌리티 취소 : CancelAbilitiesWithTag
태그로 어빌리티 차단 : BlockAbilitiesWithTag
어빌리티 실행시 태그 설정 : ActivationOwnedtags
태그가 있어야만 어빌리티 실행 : ActivationRequiredTags
태그가 있으면 어빌리티 실행 차단 : ActivationBlockedTags
시전자가 태그가 있어야 어빌리티 실행 : SourceRequiredTags
시전자에 태그가 있으면 어빌리티 차단 : SourceBlockedTags
시전 대상에 태그가 있어야 어빌리티 실행 : TargetRequiredTags
시전 대상에 태그가 있으면 어빌리티 차단 : TargetBlockedTags
블루프린트와 조합하여 특정 게임플레이 어빌리티에 대한 의존성을 없애고 게임플레이 태그를 중심으로 게임 로직을 전개 가능
태그를 사용해 헤더의 의존성을 줄일 수 있음
게임플레이 어빌리티를 만들고 태그만 필요할 때 잘 설정하면 어빌리티를 변경해도 시스템에 영향이 없기 때문에 GAS 시스템이 가지는 유연성과 확장성이 높음
UABGA_Rotate::UABGA_Rotate() {
AbilityTags.AddTag(ABTAG_ACTOR_ROTATE);
ActivationOwnedTags.AddTag(ABTAG_ACTOR_ISROTATING);
}
void AABGASFountain::PostInitializeComponents()
{
// 처음부터 인스턴스를 생성하면 부하가 클 수 있기 때문에 기본적인 정보만 보유
for (const TSubclassOf<UGameplayAbility>& Ability : Abilities)
{
FGameplayAbilitySpec AbilitySpec(Ability);
AbilitySystemComponent->GiveAbility(AbilitySpec);
}
}
void AABGASFountain::TimerAction()
{
ABGAS_LOG(LogABGAS, Log, TEXT("Begin"));
FGameplayTagContainer TargetTag(ABTAG_ACTOR_ROTATE);
if (AbilitySystemComponent->HasMatchingGameplayTag(ABTAG_ACTOR_ISROTATING) == false)
{
AbilitySystemComponent->TryActivateAbilitiesByTag(TargetTag);
}
else
{
AbilitySystemComponent->CancelAbilities(&TargetTag);
}
}
'언리얼 > 게임플레이 어빌리티 시스템' 카테고리의 다른 글
언리얼5 캐릭터 어트리뷰트 설정 (0) | 2024.11.29 |
---|---|
언리얼5 게임플레이 어빌리티를 활용한 공격 판정 시스템 (1) | 2024.11.29 |
언리얼5 게임플레이 어빌리티와 태스크를 활용한 콤보 공격과 점프 (0) | 2024.11.26 |
언리얼5 캐릭터의 게임플레이 어빌리티 시스템 캐릭터 입력 처리 (0) | 2024.11.23 |
언리얼5 게임 어빌리티 시스템(GAS) 개요 (1) | 2024.11.22 |