본문 바로가기
Unreal 게임 개발/Unreal 강의 개인 정리

Gameplay Tag - GAS

by daisy0461 2025. 8. 19.

게임플레이 태그

  • FName으로 관리되는 경량의 표식 데이터
    - 액터나 컴포넌트에 지정했던 태그와 다른 데이터이다.
  • 프로젝트 설정에서 별도로 게임플레이 태그를 생성하고 관리할 수 있다.
    - 결과는 DefaultGameplayTags.ini파일에 저장된다.
  • 계층구조로 구성되어 있어 체계적인 관리가 가능하다.
    (예시)
    - Actor.Action.Rotate:행동에 대한 태그
    - Actor.State.IsRotating : 상태에 대한 태그
  • 게임플레이 태그들의 저장소 -> GameplayTagContainer
    - 계층 구조를 지원하는 검색 기능 제공
      (Exact는 완전 동일해야한다)
    - HasTagExact : 컨테이너에 A.1태그가 있고 A로 찾으면 false, A.1은 true.
    - 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

  • 게임플레이 어빌리티 시스템과 독립적으로 사용 가능.

 

게임플레이 어빌리티와 게임플레이 태그

  • 게임 플레이 어빌리티에 부착한 태그
    - 어빌리티에 지정한 태그 (AbilityTags 태그 컨테이너)
  • 게임플레이 어빌리티에 대해 다양한 실행 조건의 설정
    - 태그로 어빌리티 취소 (CancelAbilitiesWithTag 태그 컨테이너)
    - 태그로 어빌리티 차단 (BlockAbilitiesWithTag 태그 컨테이너)
    - 어빌리티 실행 시 태그 설정 (ActivationOwnedTags 태그 컨테이너)
    - 태그가 있어야만 어빌리티 실행 (ActivationRequiredTags 태그 컨테이너)
    - 태그가 있으면 어빌리티 실행 차단 (ActivationBlockedTags 태그 컨테이너)
    - 시전자가 태그가 있어야 어빌리티 실행 (SourceRequiredTags  태그 컨테이너)
    - 시전자에 태그가 있으면 어빌리티 차단 (SourceBlockedTags 태그 컨테이너)
    - 시전 대상에 태그가 있어야 어빌리티 실행 (TargetRequiredTags 태그 컨테이너)
    - 시전 대상에 태그가 있으면 어빌리티 차단 (TargetBlockedTags 태그 컨테이너)
  • 위와 같은 게임플레이 태그를 BP와 같이 사용하면 특정 cpp와 의존성 없는 설계가 가능해진다.

 

게임플레이 태그 지정 방법

Project Settings - GameplayTag - Manage Gameplay Tags...클릭

Gameplay Tag Manager에서 +를 눌고

Name에 Actor.Action.Rotate를 Name에 작성하고 Source를 DefaultGameplayTags.ini로 설정하면
위 사진과 같이 3단 계층을 가진 태그가 생성이 된 것을 확인할 수 있다.

위 사진은 Actor.Action.Rotate와 Actor.State.IsRotating을 추가한 모습이다.

 

게임플레이 태그를 더 편하게 사용하기 위해

다음과 같이 헤더 파일을 하나 추가하고

#pragma once

#include "GameplayTagContainer.h"

#define ABTAG_ACTOR_ROTATE FGameplayTag::RequestGameplayTag(FName("Actor.Action.Rotate"))
#define ABTAG_ACTOR_ISROTATING FGameplayTag::RequestGameplayTag(FName("Actor.State.IsRotating"))

GameplayTagContainer 헤더 파일을 include하면 GameplayTag와 관련한 것들이 자동으로 include된다.
위의 예시에서 사용한 Actor.Action.Rotate와 Actor.State.IsRotating을 
RequestGameplayTag라는 함수의 FName으로 넣어서 태그가 있는지 검사한 다음에 가져올 수 있도록한다.

그리고 #define으로 전처리기로 만든 것을 확인할 수 있다.

그러면 전처리기만 사용하면 태그를 지정할 수 있게 세팅이 되는 것이다.

 

이제 실제로 GameplayTag를 통해 동작시켜보자.

이전 포스팅에 이어서 진행한다.

UABGA_Rotate::UABGA_Rotate()
{
	//어빌리티는 Actor.Action.Rotate라는 태그 이름으로 대표가 된다.
	AbilityTags.AddTag(ABTAG_ACTOR_ROTATE);
	//활성화 될 때, 발동이 될 때  Actor.State.IsRotating가 심어진다.
	ActivationOwnedTags.AddTag(ABTAG_ACTOR_ISROTATING);
}

생성자에 AbilityTag.AddTag와 ActivationOwnedTags를 통해서 어떤 태그로 표시될지, 실행 후에 어떤 태그가 심어질지 지정한다.

 

이제 Fountain으로 간다.

	UPROPERTY(EditAnywhere, Category = "GAS")
	TArray<TSubclassOf<UGameplayAbility>> StartAbilities;

헤더에는 다음과 같이 GA를 넣을 TArray를 정의하고

void AABGASFountain::PostInitializeComponents()
{
	Super::PostInitializeComponents();

	//시작 시 동작하지 않도록 자동활성화 및 비활성화
	RotatingMovement->bAutoActivate = false;
	RotatingMovement->Deactivate();

	ASC->InitAbilityActorInfo(this, this);

	for (const auto& StartAbility : StartAbilities)
	{
		FGameplayAbilitySpec StartSpec(StartAbility);
		ASC->GiveAbility(StartSpec);
	}
}

for문을 통해 Array를 돌아서 ASC에 등록을 한다.

void AABGASFountain::TimerAction()
{
	GAS_LOG(LogABGAS, Log, TEXT("Begin"));

	//발동 시킬 Tag를 넣는다.
	FGameplayTagContainer TargetTag(ABTAG_ACTOR_ROTATE);

	//HasMatchingGameplayTag은 현재 ASC에서 해당 태그가 동작하고 있는지 확인하는 것이다.
	//ABTAG_ACTOR_ISROTATING를 사용하여  해당 태그가 심어져있는지 확인하면 현재 Ability가 발동이 되고 있다고 판단할 수 있게 되는것이다.
	if (!ASC->HasMatchingGameplayTag(ABTAG_ACTOR_ISROTATING))
	{
		//ABGA_Rotate를 보면 AbilityTags에 TargetTag에 해당하는 대표 태그가 있다. -> AbilityTags.AddTag(ABTAG_ACTOR_ROTATE);
		//AbilityTags에서 ABTAG_ACTOR_ROTATE에 해당하는 정보가 있는 Tag를 검색해서 자동으로 동작시켜준다.\
		//해당 작업을 하는것이 TryActivateAbilityByTag이다.
		ASC->TryActivateAbilitiesByTag(TargetTag);
	}
	else 
	{
		ASC->CancelAbilities(&TargetTag);
	}
}

이제 Tag를 활용하여 어빌리티를 활성화하는 단계이다.

FGameplayTagContainer TargetTag에 ABTAG_ACTOR_ROTATE, 즉 "Actor.Action.Rotate" 태그를 넣어준다.

ASC->HasMatchingGameplayTag(ABTAG_ACTOR_ISROTATING)을 통해
Actor.State.IsRotating 태그가 현재 ASC에 붙어 있는지 확인한다.

UABGA_Rotate는 ActivationOwnedTags로 인해 Actor.State.IsRotating 태그를 부여하므로,
어빌리티가 활성화되어 있다면 해당 태그가 ASC에 존재하게 된다.

 

ASC->TryActivateAbilitiesByTag(TargetTag)를 호출하면,
ASC에 등록된 어빌리티 중 AbilityTags에 TargetTag를 포함하고 있는 GA들은 모두 ActivateAbility()를 실행하게 된다.

반대로, ASC->CancelAbilities(&TargetTag)를 호출하면
해당 태그를 가진 모든 실행 중인 GA가 CancelAbility()를 실행하게 된다.

 

Gameplay Tag 사용의 장점

기존에는 특정 클래스를 직접 참조하여 어빌리티를 실행해야 했지만,
이제는 GameplayTag 기반으로 어빌리티를 식별하고 실행할 수 있어 훨씬 유연하게 사용할 수 있다.

예를 들어, AbilityTag만 변경하면 다른 어빌리티로 손쉽게 교체 가능하며,
클래스 참조나 헤더 포함 없이 동작하므로 모듈 간 의존성도 크게 줄어든다.