UE5/GAS

GAS 시스템 시작

뽀또치즈맛 2025. 5. 23. 20:50

 

 

학습 실습

https://github.com/kwon1232/GAS_Study/tree/main/Lecture/2/Source

(Ability System Component)
ASC

 

어빌리티 시스템 컴포넌트를 줄여서 ASC로 불린다.

게임플레이 어빌리티 시스템을 관리하는 핵심 컴포넌트이다.

게임플레이 어빌리티 및 다양한 작업을 관리하는 처리하는 중앙 처리 장치이다.

 

액터에 단 하나만 부착할 수 있다.

액터는 부착된 ASC를 통해 게임플레이 어빌리티(GA)를 발동시킬 수 있다.

 

ASC를 부착한 액터 사이에 해당 컴포넌트를 통해 GAS 시스템의 상호작용이 가능해진다.

 

 

(Gameplay Ability)
GA

 

게임플레이 어빌리티는 줄여서 GA(Gameplay Ability)로 불린다.

ASC에 등록되어 발동시킬 수 있는 액션 명령이다.

  • 주로 공격, 마법, 특수 공격 등등에 쓰인다.
  • 간단한 액션 뿐만 아니라 상황에 따른 복잡한 액션이 수행 가능하다.

 

GA의 발동 과정

  1. ASC에 어빌리티를 등록 :
    ASC의 GiveAbility 함수에 발동할 GA의 타입을 전달
    • 발동할 GA 타입 정보를 게임플레이 어빌리티 스펙(GameplayAbliltiySpec)이라고 한다.
  2. ASC에게 어빌리티를 발동하라고 명령 :
    ASC의 TryActivateAbility 함수에 발동할 GA의 타입을 전달
    • ASC에 등록된 타입이면 GA의 인스턴스가 생성됨
  3. 발동된 GA에는 발동한 액터와 실행 정보가 기록됨
    • SpecHandle : 발동된 어빌리티에 대한 핸들
    • ActorInfo : 어빌리티의 소유자와 아바타 정보
    • ActivationInfo : 발동 방식에 대한 정보

 

GA의 주요 함수

CanActivateAbility : 어빌리티가 발동될 수 있는지 파악

ActivateAbility : 어빌리티가 발동될 때 호출 

CanCelAbility : 어빌리티가 취소될 때 호출

EndAbility : 스스로 어빌리티를 마무리할 때 호출

 

게임 플레이 태그

게임플레이 태그는 일반적인 태그와 달리 계층적 구조를 가진다.

그래서 나중에 다양한 구조로 확장이 가능하다.

게임플레이 어빌리티에 따라서 다양한 상태들을 표시가 가능하다.

 

또한 게임 플레이 태그는 검색 기능을 제공하기 때문에

계층 구조와 더불어 해당 컨테이너에 해당 태그가 있다면 해당 컴포넌트가 있는 것으로 판단 하는 등

다양한 활용이 가능하다.

 

게임 플래이 태그가 꼭 GAS만 사용되는 것은 아니다.

하지만 GAS에서 함께 높은 시너지로 유용하게 사용할 수 있는 것은 맞다.

 

특히 BP와 조합하여 특정 게임플레이 어빌리티에 대한 의존성을 없애고

게임플래이 태그 중심으로 게임 로직을 전개 가능하다.

 

 

회전하는 분수대 세 가지 방법 구현

1. 액터를 확장 : 익숙한 방법으로 빠르게 구현, 새로운 액터 기능 추가

2. GAS 사용 구현 : C++만 사용해 모든 기능 구현 가능, 액터로부터 기능 분리

3. 게임플레이 태그 추가 활용 구현 : 의존성 없는 설계 가능, 어빌리티 교체 가능

 

즉 GAS의 사용으로

액터의 역할을 최소화하는 것에 주력할 수 있다. 

 

또한 태그의 사용으로 의존성을 분리할 수 있다.

 

C++ 프로그래밍 없이도 게임플래이 태그 규약만 잘 지키면 시스템을 유연하게 확장할 수 있다.

 

액터가 가지고 있는 규모가 많아지면 1번 액터 확장으로는 기능 관리의 어려움을 느낄 수 있다.

2번 방법은 확장 설계가 가능하다는 것이 장점이다.

 

2번과 더불어 3번을 사용하면 특정 헤더의 인클루드 없이 의존성 없는 설계가 가능하며,

보다 유연하게 확장할 수 있다.

 

UABGA_Rotate::UABGA_Rotate()
{
	// Tag 부여
	AbilityTags.AddTag(ABTAG_ACTOR_ROTATE);
	// 실행 시(액션 시) Tag 부여
	ActivationOwnedTags.AddTag(ABTAG_ACTOR_ISROTATING);
}

void UABGA_Rotate::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
	Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);

	// 아바타 액터 가져오기
	AActor* AvatarActor = ActorInfo->AvatarActor.Get();
	// 아바타 액터가 유효하다면
	if (AvatarActor)
	{
		/*
		* URotatingMovementComponent::StaticClass() → 컴포넌트의 타입 정보
		* GetComponentByClass(...) → 그 타입에 해당하는 붙어 있는 실제 인스턴스
		* Cast<>() → 그걸 URotatingMovementComponent* 타입으로 변환
		* Activate(true) → 그 인스턴스를 작동시킴
		* 
		* StaticClass()				타입 정보 (설계도) 가져오기
		* GetDefaultObject()		클래스의 "기본 객체(CDO)", 설정값 참고용 가져오기
		* GetComponentByClass()		실제 게임 안에서 생성된 인스턴스 가져오기
		*/
		URotatingMovementComponent* RotatingMovement = Cast<URotatingMovementComponent>(AvatarActor->GetComponentByClass(URotatingMovementComponent::StaticClass()));
		if (RotatingMovement)
		{
			RotatingMovement->Activate(true);
		}
	}
}