Single Source of Truth
모든 시스템은 현재 상태를 직접 판단하지 말고 State Machine을 기준으로 판단해야 한다.
void OnAttack()
{
if (StateMachine->GetCurrentState() != ECleaningState::Idle)
{
return;
}
Attack();
}
void TakeDamage(float Damage)
{
if (StateMachine->GetCurrentState() == ECleaningState::Cleaning)
{
return;
}
Health -= Damage;
}
State Machine을 기준으로 삼으면 UI, 전투, 입력, 애니메이션 시스템이 서로 다른 상태를 바라보는 문제를 줄일 수 있다.
설계 원칙
단일 책임 원칙
각 클래스는 하나의 책임만 가져야 한다.
| 클래스 | 책임 |
|---|---|
UContextManagerComponent |
입력 Context 관리 |
UCleaningStateMachine |
행동 상태와 전이 관리 |
AEnhancedChallengeCharacter |
입력 위임 및 시스템 연결 |
나쁜 구조는 다음처럼 하나의 함수에 모든 책임이 모이는 형태다.
void ACharacter::OnInteract()
{
if (CurrentMode == CleaningMode)
{
PlayMontage();
UpdateHUD();
PlaySound();
}
}
좋은 구조는 입력 해석, 상태 판단, 실제 표현을 분리하는 것이다.
ContextManager
→ 현재 입력 모드 판단
StateMachine
→ 현재 행동 가능 여부 판단
Character
→ 각 시스템 호출
개방-폐쇄 원칙
기능 확장에는 열려 있고, 기존 코드 수정에는 닫혀 있어야 한다.
새로운 Context를 추가할 때 기존 입력 함수를 계속 수정하는 구조는 좋지 않다.
Enhanced Input과 ContextManager를 사용하면 새로운 Context를 추가하는 방식으로 확장할 수 있다.
enum class EGameplayContext : uint8
{
Default,
FloorCleaning,
WindowCleaning,
Fishing
};
추가 절차는 다음과 같다.
1. IMC_Fishing 생성
2. EGameplayContext::Fishing 추가
3. ContextMappings에 등록
기존 입력 처리 코드를 크게 수정하지 않고 새로운 입력 모드를 추가할 수 있다.
의존성 역전 원칙
구체적인 키 입력에 의존하지 않고, 추상적인 입력 의도에 의존해야 한다.
나쁜 방식
if (IsKeyPressed(EKeys::E))
{
CleanFloor();
}
이 코드는 키보드 E 키에 직접 의존한다.
게임패드, VR 컨트롤러, 키 리바인딩을 지원하려면 코드 수정이 필요하다.
좋은 방식
void OnInteract(const FInputActionValue& Value)
{
ExecuteInteraction();
}
OnInteract는 어떤 키가 눌렸는지 모른다.
단지 “상호작용 의도”가 발생했다는 사실만 처리한다.
멀티 도구 시스템
enum class EGameplayContext : uint8
{
FloorCleaning,
WindowCleaning,
CarCleaning,
Sword,
Bow,
Magic,
OnFoot,
InCar,
InBoat
};
각 Context마다 다른 IMC를 등록하면, 같은 입력이라도 상황에 따라 완전히 다른 조작 체계를 만들 수 있다.
복합 State Machine
class ACharacter
{
UCleaningStateMachine* CleaningState;
UCombatStateMachine* CombatState;
UMovementStateMachine* MovementState;
};
void OnAttack()
{
if (CombatState->CanAttack() &&
CleaningState->IsIdle() &&
MovementState->CanAct())
{
Attack();
}
}
여러 FSM을 병렬로 운용하면 전투, 이동, 상호작용 상태를 분리해서 관리할 수 있다.
데이터 주도 설계
USTRUCT()
struct FContextDefinition
{
EGameplayContext ContextType;
UInputMappingContext* IMC;
TArray<UAnimMontage*> AvailableActions;
float StaminaCost;
};
Context 정의를 Data Asset으로 분리하면 디자이너가 코드 수정 없이 입력 모드, 행동, 비용 등을 조정할 수 있다.
Input 내용 요약
Enhanced Input System은 기존 입력 방식처럼 키 입력을 직접 함수에 연결하고 내부에서 조건문으로 분기하는 구조를 개선한다.
키 입력
↓
InputAction
↓
Input Mapping Context
↓
ContextManager
↓
StateMachine
↓
실제 행동
각 요소의 역할은 명확히 분리된다.
| 요소 | 역할 |
|---|---|
| InputAction | 입력 의도 정의 |
| Modifier | 입력값 변환 |
| Trigger | 입력 발동 조건 판단 |
| Input Mapping Context | 키와 InputAction 연결 |
| Enhanced Input Subsystem | 활성 Context 관리 |
| ContextManager | 게임 상황 의미 부여 |
| StateMachine | 현재 행동 가능 여부 판단 |
결론적으로 Enhanced Input을 제대로 활용하려면 단순히 BindAction을 사용하는 것에서 끝나면 안 된다.
InputAction, Mapping Context, ContextManager, State Machine을 함께 설계해야 확장 가능하고 유지보수하기 쉬운 입력 구조를 만들 수 있다.
'Unreal Engine' 카테고리의 다른 글
| 언리얼 레퍼런스 (0) | 2026.06.29 |
|---|---|
| DataTable, DataAsset (0) | 2026.06.26 |
| UE Input 2 (0) | 2026.06.24 |
| UE Input 1 (0) | 2026.06.23 |
| GameplayTag Static vs GameplayTag Extern (0) | 2026.06.22 |