📌 작업 목적
GAS(Gameplay Ability System)를 사용하는 프로젝트에서
입력(Input)을 Ability에 직접 연결하지 않고, GameplayTag를 매개로 추상화하는 구조를 설계 및 구현.
목표:
- 입력 시스템과 Ability 시스템을 느슨하게 분리
- 데이터 중심 설계로 확장성 확보
- 캐릭터별 입력 구성 분리 가능
- GAS 철학(Tag 기반 설계)에 맞춘 구조 정립
1. 전체 아키텍처 개요
🔁 입력 → Ability 실행 흐름
[키/패드 입력]
↓
InputAction (Enhanced Input)
↓
InputTag (GameplayTag)
↓
AbilitySystemComponent
↓
해당 InputTag를 가진 Ability Activate
핵심 개념
- InputAction은 입력 계층
- Ability는 게임플레이 계층
- 둘을 직접 연결하지 않음
- 대신 GameplayTag를 중간 계층으로 사용
2. 왜 이 구조를 선택했는가?
❌ 단순 연결 방식의 문제점
IA_Attack → GA_Attack 직접 실행
문제:
- Ability 변경 시 입력 코드 수정 필요
- 플랫폼 변경 시 구조 수정 발생
- 캐릭터별 입력 구성 분리 어려움
- GAS 철학과 불일치
✅ GameplayTag 기반 구조의 장점
InputAction → InputTag → ASC → Ability
항목효과
| 느슨한 결합 | 입력과 Ability가 Tag로만 연결 |
| 데이터 중심 | DataAsset 수정으로 입력 변경 가능 |
| 확장성 | 캐릭터별 InputConfig 교체 가능 |
| GAS 친화 | Ability Input Tag와 자연스럽게 연결 |
| 네트워크 안정성 | Ability 실행은 ASC가 담당 |
3. 단계별 구현 정리
① Native Gameplay Tags 정의
목적
입력을 문자열이나 키값이 아닌 GameplayTag로 관리하기 위함.
구현
DirectGameplayTags.h
namespace DirectGameplayTags
{
DIRECT_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_Move);
DIRECT_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_Look);
DIRECT_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_Roll);
}
DirectGameplayTags.cpp
UE_DEFINE_GAMEPLAY_TAG(InputTag_Move, "InputTag.Move");
UE_DEFINE_GAMEPLAY_TAG(InputTag_Look, "InputTag.Look");
UE_DEFINE_GAMEPLAY_TAG(InputTag_Roll, "InputTag.Roll");
설계 의도
- Ability는 "InputTag.Roll"만 인지
- 실제 키는 몰라도 됨
- 키 변경 시 Ability 수정 불필요
② Input Config Data Asset 설계
목적
InputTag ↔ InputAction 매핑을 데이터화
구조
USTRUCT(BlueprintType)
struct FDirectInputActionConfig
{
UPROPERTY(EditDefaultsOnly, meta = (Categories = "InputTag"))
FGameplayTag InputTag;
UPROPERTY(EditDefaultsOnly)
UInputAction* InputAction;
};
UCLASS()
class UDataAsset_InputConfig : public UDataAsset
{
UPROPERTY(EditDefaultsOnly)
UInputMappingContext* DefaultMappingContext;
UPROPERTY(EditDefaultsOnly)
TArray<FDirectInputActionConfig> NativeInputActions;
};
에디터에서 설정
InputTagInputAction
| Move | IA_Move |
| Roll | IA_Roll |
설계 포인트
- 코드 수정 없이 입력 교체 가능
- 캐릭터별 DataAsset 교체 가능
- 플랫폼 대응 유리
③ Custom Input Component 제작
목적
Tag 기반 바인딩 API 제공
구현
UCLASS()
class UDirectInputComponent : public UEnhancedInputComponent
{
template<class UserObject, typename CallbackFunc>
void BindNativeInputAction(
const UDataAsset_InputConfig* InputConfig,
const FGameplayTag& InputTag,
ETriggerEvent TriggerEvent,
UserObject* ContextObject,
CallbackFunc Func);
};
내부 동작
- InputTag로 InputAction 검색
- EnhancedInput BindAction 호출
- 입력 발생 시 콜백 실행
④ Character에서 실제 바인딩
위치
ADirectBaseCharacter::SetupPlayerInputComponent
예시
InputComponent->BindNativeInputAction(
InputConfig,
DirectGameplayTags::InputTag_Roll,
ETriggerEvent::Started,
this,
&ThisClass::Input_AbilityPressed);
콜백 처리
void ADirectBaseCharacter::Input_AbilityPressed(FGameplayTag InputTag)
{
AbilitySystemComponent->AbilityInputTagPressed(InputTag);
}
4. Ability 쪽 연결 방식
Ability 클래스에서:
Ability Input Tag = InputTag.Roll
ASC 내부에서:
- 입력 Tag와 Ability의 InputTag 비교
- 일치 시 ActivateAbility
이로 인해 Ability는 입력 키를 전혀 모른다.
5. 에디터 설정 단계
필수 설정:
- Input Mapping Context (IMC)
- DataAsset_InputConfig 지정
- Character/Controller에 적용
이 단계가 빠지면 입력이 동작하지 않음.
6. Direct 프로젝트 구조 정리
Source/Direct/
├── DirectGameplayTags ← 입력 태그 정의
├── DataAsset_InputConfig ← Tag ↔ Action 매핑
├── DirectInputComponent ← Tag 기반 바인딩
├── DirectBaseCharacter ← 실제 입력 바인딩
└── Ability 클래스들 ← Ability Input Tag 지정
7. 이번 작업의 핵심 성과
- GAS 친화적인 입력 아키텍처 설계 완료
- 입력-Ability 완전 분리 구조 확립
- 캐릭터별 입력 구성 교체 가능 구조 확보
- 유지보수성과 확장성 고려한 데이터 중심 설계 적용
'IT > 언리얼_포트폴리오' 카테고리의 다른 글
| 4일차. IK_FootRig 구현 흐름 문서 (0) | 2026.02.17 |
|---|---|
| 3일차. GAS 기반 애니메이션 레이어 구조 설계 (0) | 2026.02.15 |
| 1일차. AAA급 액션 RPG를 목표로, 언리얼 5.6 + GAS로 시작 (0) | 2026.02.11 |