역량강화 분반 - 챌린지 - 이론
스테이트 머신
▷ 객체가 어떤 상태인지 명확히 정하고, 그 상태에서만 가능한 행동과 전환을 허용하는 구조
직접 구현 VS 스테이트 머신
더보기
직접 구현 (나쁜 예시)
- 상태 플래그 여러 개가 동시에 true가 될 수 있음 (논리 오류)
- if문 순서가 중요함 (순서 바뀌면 버그)
- 새 상태 추가 시 모든 곳 수정
- 디버깅 극악의 난이도
// 캐릭터 클래스
class Character {
bool bIsIdle = true;
bool bIsWalking = false;
bool bIsRunning = false;
bool bIsJumping = false;
bool bIsAttacking = false;
bool bIsDead = false;
void Update(float DeltaTime) {
// if 지옥...
if (bIsDead) {
// Dead 로직
return;
}
if (bIsAttacking) {
if (AttackAnimFinished()) {
bIsAttacking = false;
bIsIdle = true;
}
return;
}
if (bIsJumping) {
if (IsOnGround()) {
bIsJumping = false;
bIsIdle = true;
}
// Jump 물리...
return;
}
if (InputAttack()) {
bIsIdle = false;
bIsWalking = false;
bIsRunning = false;
bIsAttacking = true;
// 공격 시작
return;
}
if (InputJump()) {
bIsIdle = false;
bIsWalking = false;
bIsRunning = false;
bIsJumping = true;
// 점프 시작
return;
}
if (InputMove()) {
bIsIdle = false;
if (InputSprint()) {
bIsWalking = false;
bIsRunning = true;
// Run 로직
} else {
bIsWalking = true;
bIsRunning = false;
// Walk 로직
}
} else {
bIsWalking = false;
bIsRunning = false;
bIsIdle = true;
// Idle 로직
}
}
};
더보기
스테이트 머신 (좋은 예시)
// 상태 정의
enum class CharacterState {
Idle,
Walk,
Run,
Jump,
Attack,
Dead
};
class Character {
CharacterState CurrentState = CharacterState::Idle;
void Update(float DeltaTime) {
// 현재 상태에서만 로직 실행
switch (CurrentState) {
case CharacterState::Idle:
UpdateIdle(DeltaTime);
break;
case CharacterState::Walk:
UpdateWalk(DeltaTime);
break;
case CharacterState::Run:
UpdateRun(DeltaTime);
break;
case CharacterState::Jump:
UpdateJump(DeltaTime);
break;
case CharacterState::Attack:
UpdateAttack(DeltaTime);
break;
case CharacterState::Dead:
UpdateDead(DeltaTime);
break;
}
}
void ChangeState(CharacterState NewState) {
// 상태 전환
CurrentState = NewState;
}
};
오토마타
▷ 계산 이론(Theory of Computation)에서 사용하는 추상적인 계산 모델
▷ 입력을 받아서 상태를 전환하며, 출력을 생성하는 수학적 기계
구성 요소
- States (상태들): Q = {q₀, q₁, q₂, …}
- Input Alphabet (입력 기호): Σ = {a, b, c, …}
- Transition Function (전환 함수): δ(q, a) = q’
- Initial State (초기 상태): q₀
- Accepting States (수락 상태, 완료): F ⊆ Q
오토마타의 종류
| 종류 | 용도 | 설명 |
| 유한 오토마타 (FA) | 정규표현식, 게임 AI | 유한한(현재) 상태만 저장 |
| 푸시다운 오토마타 (PDA) | 파서, 컴파일러 | 현재 상태 + 스택 메모리 추가 |
| 튜링 머신 (TM) | 이론적 계산 모델 | 무한(이론상) 테이프 메모리 |
📌게임에서는 유한 오토마타 (Finite Automaton), DFA 만 사용!
유한 상태 기계 (FSM)
캐릭터 FSM 다이어그램 예시

1. Enter (OnEnter, OnStateBegin)
- 상태에 진입할 때 한 번 실행
- 공격 애니메이션 재생, 효과음
2. Update (Tick, OnStateUpdate)
- 상태가 활성화된 동안 매 프레임 실행
- 이동, 물리 계산
3. Exit (OnExit, OnStateEnd)
- 상태를 떠날 때 한 번 실행
- 정리 작업, 다음 상태 준비
FSM 구현 방법
1. Enum + Switch
▷ 가장 간단하고 직관적인 방법
더보기
// CharacterFSM_Enum.h
#pragma once
enum class ECharacterState {
Idle,
Jump,
Attack,
Dead
};
class CharacterFSM_Enum {
private:
ECharacterState CurrentState;
public:
CharacterFSM_Enum() : CurrentState(ECharacterState::Idle) {}
void Update(float DeltaTime) {
switch (CurrentState) {
case ECharacterState::Idle:
UpdateIdle(DeltaTime);
break;
case ECharacterState::Jump:
UpdateJump(DeltaTime);
break;
case ECharacterState::Attack:
UpdateAttack(DeltaTime);
break;
case ECharacterState::Dead:
UpdateDead(DeltaTime);
break;
}
}
void ChangeState(ECharacterState NewState) {
// Exit current state
ExitState(CurrentState);
// Change state
ECharacterState OldState = CurrentState;
CurrentState = NewState;
// Enter new state
EnterState(NewState);
// 로그
printf("State changed:%d ->%d\n", (int)OldState, (int)NewState);
}
private:
void EnterState(ECharacterState State) {
switch (State) {
case ECharacterState::Idle:
printf("Enter Idle\n");
break;
case ECharacterState::Attack:
printf("Enter Attack: Play attack animation\n");
break;
case ECharacterState::Dead:
printf("Enter Dead: Character died\n");
break;
}
}
void ExitState(ECharacterState State) {
switch (State) {
case ECharacterState::Attack:
printf("Exit Attack: Cleanup\n");
break;
// 다른 상태는 Exit 처리 없음 (필요 시 추가)
}
}
void UpdateIdle(float DeltaTime) {
// Idle 로직
// 예: 입력 대기
}
void UpdateJump(float DeltaTime) {
// Jump 로직
// 예: 착지 체크
if (IsOnGround()) {
ChangeState(ECharacterState::Idle);
}
}
void UpdateAttack(float DeltaTime) {
// Attack 로직
// 예: 애니메이션 종료 체크
if (IsAttackFinished()) {
ChangeState(ECharacterState::Idle);
}
}
void UpdateDead(float DeltaTime) {
// Dead 로직
// (아무것도 안 함)
}
// 헬퍼 함수들
bool IsOnGround() {
//TODO: 실제 구현
return false;
}
bool IsAttackFinished() {
//TODO: 실제 구현
return false;
}
};
2. State Pattern
▷ GoF Design Pattern 중 하나인 State Pattern을 사용

더보기
IState.h (인터페이스)
#pragma once
class CharacterFSM_StatePattern; // 전방 선언
// 상태 인터페이스
class IState {
public:
virtual ~IState() = default;
// 상태 진입
virtual void OnEnter(CharacterFSM_StatePattern* Owner) = 0;
// 상태 업데이트
virtual void OnUpdate(CharacterFSM_StatePattern* Owner, float DeltaTime) = 0;
// 상태 탈출
virtual void OnExit(CharacterFSM_StatePattern* Owner) = 0;
};
IdleState.h:
#pragma once
#include"IState.h"
#include<iostream>
class IdleState : public IState {
public:
void OnEnter(CharacterFSM_StatePattern* Owner) override {
std::cout << "[Idle] Enter: Character is idle\n";
}
void OnUpdate(CharacterFSM_StatePattern* Owner, float DeltaTime) override {
// Idle 로직
// 예: 입력 대기, Idle 애니메이션
}
void OnExit(CharacterFSM_StatePattern* Owner) override {
std::cout << "[Idle] Exit\n";
}
};
... 생략
State Pattern이란?
객체가 특정 상태에 따라 행위를 달리하는 상황에서, 상태를 조건문으로 검사해서 행위를 달리하는 것이 아닌, 상태를 객체화 하여 상태가 행동을 할 수 있도록 위임하는 패턴
- 각 상태를 클래스로 만듦
- 다형성 활용 (가상 함수)
- 상태별 로직 캡슐화
계층적 상태 기계 (HSM, Hierarchical State Machine)
▷ 상태를 계층적으로 구성한 FSM

그냥 상속받아서 만들면 안되나요?
📌됩니다. 다만 trade-off가 있습니다.
상속을 쓰면 계층 구조가 타입 시스템에 고정됩니다. 상태 타입과 계층을 분리하지 않는다면,
- 상태를 동적으로 재구성하기 어렵고
- 하나의 상태가 여러 상위 개념을 갖기 힘듭니다.
- Attack이 Combat이면서 동시에 Airborne 계열일 수도 있다면? → 다중 상속 </aside>
Unreal Engine과의 연관성
1. Animation Blueprint의 State Machine은 HSM

2. StateTree는 UE5의 새로운 AI 시스템으로, HSM + Behavior Tree의 장점을 결합

특징
- 계층적 상태
- 선택자 (Selector): 조건에 따라 상태 선택
- 태스크 (Task): 상태에서 실행할 동작
- 평가자 (Evaluator): 조건 평가
- GAS 연동: GameplayTag 기반 조건
3. Behavior Tree는 FSM의 대안
| FSM | Behavior Tree |
| 상태 중심 | 행동 중심 |
| 전환 명시적 | 전환 자동 (우선순위) |
| 다이어그램: 그래프 | 다이어그램: 트리 |

UBehaviorTreeComponent가 틱마다
- 루트부터 내려가며 조건(Decorator) 평가
- 우선순위에 맞는 경로를 선택
- 선택된 Task를 실행(진행 중이면 계속 Tick)
📌전환을 명시적으로 연결한다기보다 조건/우선순위로 자동 선택한다
4. Gameplay Ability System (GAS)는 Tag 기반 FSM

'내배캠Unreal_TIL > UE' 카테고리의 다른 글
| [TIL] 2026-01-26 | Attribute System (0) | 2026.01.26 |
|---|---|
| [TIL] 2026-01-23 | 캐릭터 에셋 끄적거리기, 리깅이 안되어 있을 때 (4) | 2026.01.23 |
| [TIL] 2026-01-22 | UE GameplayTags (0) | 2026.01.22 |
| [TIL] 2026-01-21 | UE 게임 기초 시스템 구현 (0) | 2026.01.21 |
| [TIL] 2026-01-20 | 과제 6에 타이머로 자동문 추가 (2) | 2026.01.20 |