스테이트 머신의 기본 활용
Idle과 Walk_Run 상태 및 속도 기반 전환 규칙을 만들고, 이동 상태 안에서 걷기와 달리기를 블렌딩합니다.
캐릭터의 동작이 대기와 이동 두 가지뿐이라면 Blend Poses by bool 하나로도 충분해 보입니다. 하지만 점프, 착지, 공격이 더해지면 "지금 어떤 동작 중이고, 무슨 조건에서 다음 동작으로 넘어가는가"를 한곳에서 관리할 방법이 필요해집니다. 스테이트 머신(State Machine)은 이 질문에 상태와 전환 규칙이라는 두 가지 요소로 답합니다.
이 글에서는 스테이트 머신이 무엇이고 왜 쓰는지 살펴본 뒤, 앞 글에서 만든 구조를 넓혀 Idle과 Walk_Run 두 상태를 캐릭터의 실제 속도로 전환해 봅니다. 이동 상태 안에서는 걷기와 달리기를 블렌드 스페이스로 섞고, 마지막으로 전환 블렌딩과 우선순위처럼 상태가 늘어날 때 알아야 할 설정을 정리합니다.
상태와 전환 규칙으로 동작을 나누기
스테이트 머신은 정해진 조건에 따라 캐릭터의 애니메이션 상태를 전환하고 관리하는 애님 그래프 노드입니다. 신호등이 빨간불, 노란불, 초록불이라는 상태를 가지고 정해진 규칙에 따라 상태를 바꾸는 것과 비슷합니다. 캐릭터 애니메이션에서 상태는 보통 하나의 행동을 나타내며, Idle(대기), Walk(걷기), Run(달리기), Jump(점프), Attack(공격) 같은 것이 상태가 됩니다. 신호등은 시간이 되면 바뀌지만 캐릭터의 상태는 속도나 공중 여부 같은 게임의 값으로 바뀐다는 점이 다릅니다.
스테이트 머신을 쓰면 캐릭터가 지금 어느 상태에 있는지를 그래프에서 바로 볼 수 있습니다. 상태 사이의 전환 규칙마다 조건을 따로 두므로, 다양한 동작 조합과 전환 로직을 하나의 구조 안에서 정리할 수 있습니다. 상태가 바뀔 때는 두 애니메이션을 섞어 동작이 갑자기 끊기지 않게 하고, 어떤 동작이 이상하게 재생되면 그 상태와 그 상태로 들어오는 전환 규칙만 살펴보면 되므로 문제를 찾기도 쉬워집니다.
스테이트 머신 노드를 더블클릭해 안으로 들어가면 두 종류의 요소가 보입니다. 상태(State)는 캐릭터의 한 가지 행동을 나타내는 상자 모양의 노드이고, 그 안에 해당 상태에서 재생할 애니메이션 시퀀스나 블렌드 스페이스 같은 포즈 로직이 들어갑니다. Entry 노드는 스테이트 머신이 처음 평가될 때 들어갈 상태를 가리킵니다. 전환 규칙(transition rule)은 두 상태를 잇는 화살표로, 한 상태에서 다른 상태로 넘어갈 수 있는 경로를 나타냅니다. 화살표 위의 규칙 아이콘을 더블클릭하면 그 전환이 일어날 조건을 정의하는 전환 그래프가 열리며, 이 그래프는 불리언 값 하나를 내놓아 참이면 전환이 시작됩니다.
공식 문서에 따르면 전환은 한 방향으로만 동작합니다. 그래서 두 상태를 오가려면 방향마다 전환을 하나씩 따로 만들어야 합니다. 상태 상자보다 이 연결선의 조건이 실제 동작을 결정하므로, 스테이트 머신을 읽을 때는 Entry에서 시작해 각 전환 규칙을 거쳐 다시 돌아오는 흐름을 따라가면 구조를 놓치지 않습니다.
Idle과 Walk_Run 상태 만들기
이제 Idle과 Walk_Run 두 상태를 만들고, 이동 상태 안에서 걷기와 달리기를 블렌드 스페이스로 섞어 보겠습니다. 이 구조는 대부분의 캐릭터 애니메이션 시스템의 기본이 됩니다. 필요한 에셋은 캐릭터와 호환되는 스켈레톤을 쓰는 다음 두 가지입니다.
Idle애니메이션 시퀀스 한 개. 에셋 이름은 프로젝트마다 다릅니다.BS_WalkRun: 축 이름이Speed이고,Idle,Walk,Run애니메이션을 샘플로 넣은 Blend Space 1D 에셋입니다.
아직 BS_WalkRun이 없다면 블렌드 스페이스 기본 사용법의 생성 및 설정 부분까지만 먼저 진행해 에셋을 저장한 뒤 이 글로 돌아오면 됩니다. 애님 블루프린트에 연결하는 작업은 아래에서 함께 합니다.
같은 Speed 경계의 두 방향 전환을 모두 연결합니다
Entry가 Idle로 진입한 뒤 Speed>0.1이면 Walk_Run, <=0.1이면 Idle로 돌아가는 실제 선택 상태 변화이다. 조건과 포즈 전환 블렌딩은 구분한다.
ENTRY · STATE · TRANSITION RULE
같은 Speed 경계의 두 방향 전환을 모두 연결합니다
지상 이동 예제는 XY 속도를 Speed에 저장합니다. Entry는 Idle을 선택하고, Speed가 0.1보다 크면 Walk_Run으로, 0.1 이하이면 Idle로 돌아갑니다.
Idle 상태 내부
Idle 시퀀스 플레이어를 Output Pose에 연결합니다.
Walk_Run 상태 내부
Blend Space Player가 Speed를 읽어 걷기·달리기 포즈를 섞고 Output Pose로 보냅니다.
선의 조건과 전환 블렌딩을 구분합니다
조건은 어느 상태로 이동할지 정합니다. Transition Duration·Blend Mode는 전환 때 포즈를 섞는 방식입니다. 경계에서 떨린다면 진입·복귀 임계값을 다르게 두는 설계를 검토합니다.
이 예의 조건
- 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
- 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
| 범위 | 원문 |
|---|---|
| 도표 제목 | Idle과 Walk_Run의 두 방향 전환 |
| 관계·조건 설명 | Entry는 Idle로 진입한다. Speed가 0.1보다 크면 Walk_Run으로, Speed가 0.1 이하이면 Idle로 전환한다. 두 화살표는 다른 방향의 전환 규칙이다. |
| 관계·조건 설명 | Entry는 Idle로 진입한다. 왼쪽 아래 화살표는 Speed>0.1일 때 Walk_Run으로, 오른쪽 위 화살표는 Speed≤0.1일 때 Idle로 복귀한다. 같은 경계와 두 방향 조건을 유지한다. |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| Idle 시작 Entry 뒤 Idle 상태에서 Speed를 읽는다. |
|
|
| 이동 상태 0.1보다 크면 Walk_Run으로 전환한다. |
|
|
| 정지 복귀 0.1 이하에서 Idle로 돌아간다. |
|
|
같은 Speed 경계의 두 방향 전환을 모두 연결합니다
Entry가 Idle로 진입한 뒤 Speed>0.1이면 Walk_Run, <=0.1이면 Idle로 돌아가는 실제 선택 상태 변화이다. 조건과 포즈 전환 블렌딩은 구분한다.
ENTRY · STATE · TRANSITION RULE
같은 Speed 경계의 두 방향 전환을 모두 연결합니다
지상 이동 예제는 XY 속도를 Speed에 저장합니다. Entry는 Idle을 선택하고, Speed가 0.1보다 크면 Walk_Run으로, 0.1 이하이면 Idle로 돌아갑니다.
Idle 상태 내부
Idle 시퀀스 플레이어를 Output Pose에 연결합니다.
Walk_Run 상태 내부
Blend Space Player가 Speed를 읽어 걷기·달리기 포즈를 섞고 Output Pose로 보냅니다.
선의 조건과 전환 블렌딩을 구분합니다
조건은 어느 상태로 이동할지 정합니다. Transition Duration·Blend Mode는 전환 때 포즈를 섞는 방식입니다. 경계에서 떨린다면 진입·복귀 임계값을 다르게 두는 설계를 검토합니다.
이 예의 조건
- 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
- 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
| 범위 | 원문 |
|---|---|
| 도표 제목 | Idle과 Walk_Run의 두 방향 전환 |
| 관계·조건 설명 | Entry는 Idle로 진입한다. Speed가 0.1보다 크면 Walk_Run으로, Speed가 0.1 이하이면 Idle로 전환한다. 두 화살표는 다른 방향의 전환 규칙이다. |
| 관계·조건 설명 | Entry는 Idle로 진입한다. 왼쪽 아래 화살표는 Speed>0.1일 때 Walk_Run으로, 오른쪽 위 화살표는 Speed≤0.1일 때 Idle로 복귀한다. 같은 경계와 두 방향 조건을 유지한다. |
| 관찰·상황 | 값·보충 정보 | 변화·이유 |
|---|---|---|
| Idle 시작 Entry 뒤 Idle 상태에서 Speed를 읽는다. |
|
|
| 이동 상태 0.1보다 크면 Walk_Run으로 전환한다. |
|
|
| 정지 복귀 0.1 이하에서 Idle로 돌아간다. |
|
|
위 그림은 이 절에서 완성할 스테이트 머신입니다. 지상 이동 예제는 캐릭터의 수평(XY) 속도를 Speed에 저장하고, Entry는 Idle을 처음 상태로 고릅니다. Idle에서 Walk_Run으로 가는 화살표에는 Speed > 0.1, 반대 방향 화살표에는 Speed ≤ 0.1 조건이 붙어 있어, 같은 기준값을 두 방향 전환이 나누어 씁니다. 아래쪽 상자는 각 상태의 내부로, Idle은 Idle 시퀀스 플레이어를 Output Pose에 연결하고, Walk_Run은 블렌드 스페이스 플레이어가 Speed를 읽어 걷기와 달리기 포즈를 섞은 뒤 Output Pose로 보냅니다.
단계 그림은 같은 구조가 동작하는 순서를 세 단계로 보여 줍니다. 첫 단계에서 Entry 다음의 Idle 상태가 Speed를 읽고, 둘째 단계에서 그 값이 0.1보다 커지면 Walk_Run으로 전환합니다. 셋째 단계에서 값이 0.1 이하로 떨어지면 다시 Idle로 돌아갑니다. 그림 아래의 설명처럼 조건은 어느 상태로 갈지를 정하고, 전환할 때 포즈를 섞는 방식은 따로 설정합니다. 그림에서 Transition Duration과 Blend Mode라고 적은 설정은 5.8의 전환 규칙 디테일 패널에서 Duration, Mode, Blend Logic 항목으로 표시됩니다.
이벤트 그래프에서 Speed 갱신하기
먼저 캐릭터 스켈레톤에 연결된 애님 블루프린트(예: ABP_Mannequin)를 열고 이벤트 그래프로 갑니다. Event Blueprint Update Animation 노드는 애니메이션이 갱신될 때마다 호출되는 이벤트입니다. 호출 주기는 틱과 최적화 설정에 따라 달라질 수 있지만, 보통은 매 프레임 실행된다고 보면 됩니다.
다음으로 Try Get Pawn Owner 노드를 놓아 이 애님 블루프린트를 쓰는 폰(Pawn), 즉 캐릭터의 참조를 얻습니다. 애님 블루프린트는 에디터 미리보기처럼 폰이 없는 곳에서도 실행되므로, 그 Return Value를 Is Valid 노드에 이어 폰이 유효한지부터 확인합니다. 업데이트 이벤트의 실행 선을 Is Valid에 잇고, Is Valid 실행 출력 뒤에 Cast To Character를 둡니다. 플레이어 캐릭터 블루프린트의 변수까지 읽어야 한다면 Cast To BP_PlayerCharacter처럼 그 블루프린트로 캐스팅해도 됩니다.
캐스팅에 성공하면 결과 핀(As Character)에서 Get Velocity를 호출해 현재 속도 벡터를 얻습니다. 이 예제는 지상 이동만 다루므로 Get Velocity의 출력을 Vector Length XY에 이어, 수직 속도를 뺀 수평 속도의 크기를 구합니다. 애님 블루프린트에 Float 타입의 Speed 변수를 추가하고(앞 글에서 이미 추가했다면 그 변수를 씁니다), 캐스팅 성공 실행 출력을 Set Speed의 실행 입력에, 계산한 값을 Set Speed의 값 입력에 연결합니다. 이 Speed는 뒤에서 전환 규칙과 블렌드 스페이스가 함께 읽습니다. 연결을 마쳤으면 컴파일하고 저장합니다.
Speed의 단위도 블렌드 스페이스의 축과 맞춰야 합니다. 기본 거리 단위가 cm인 프로젝트에서 속도가 (300, 400, 1200) cm/s라면, 이 실습의 Vector Length XY는 √(300² + 400²) = 500 cm/s입니다. Z 성분 1200까지 넣어 계산하는 전체 벡터 길이는 √(300² + 400² + 1200²) = 1300 cm/s이므로, 두 값을 구별해서 써야 합니다.
애님 그래프에서 상태 구성하기
애님 그래프 탭으로 가서, 앞 글에서 추가한 Default State Machine이 최종 Output Pose에 연결되어 있는지 확인한 뒤 안으로 들어갑니다. Entry에서 Idle로 가는 선이 없다면 Entry의 출력에서 드래그해 놓고 Add State를 골라 Idle 상태를 만듭니다. Idle을 더블클릭해 Idle 애니메이션 에셋을 끌어다 놓아 시퀀스 플레이어를 만들고, 그 포즈를 상태의 Output Animation Pose에 연결합니다.
앞 글에서 WalkRun 상태를 이미 만들었다면 새로 만들지 말고, 그 상태의 이름을 Walk_Run으로 바꿔 그대로 씁니다. 아직 이동 상태가 없다면 Idle 상태의 테두리에서 드래그해 Add State를 골라 Walk_Run 상태를 만듭니다. 이렇게 드래그로 만들면 두 상태 사이의 전환도 함께 생깁니다. Walk_Run을 더블클릭해 들어가 BS_WalkRun 에셋을 끌어다 놓으면 블렌드 스페이스 플레이어가 생기며, 그 Speed 입력에 애님 블루프린트의 Speed 변수를 Get 노드로 연결하고 포즈 출력을 Output Animation Pose에 연결합니다.
두 방향의 전환 규칙 정하기
Idle에서 Walk_Run으로 가는 전환의 규칙 아이콘을 더블클릭하고, Can Enter Transition에 들어갈 조건을 만듭니다. Speed 변수를 Get 노드로 가져와 >(보다 큼) 노드로 0.1과 비교합니다. 앞 글에서 이 전환에 0과 비교하는 조건을 두었다면 비교값만 0.1로 바꿉니다. 0 대신 작은 값을 쓰는 이유는 거의 멈춘 상태의 미세한 움직임까지 이동으로 보지 않기 위해서입니다.
Walk_Run에서 Idle로 가는 전환이 아직 없다면 Walk_Run의 테두리에서 Idle로 드래그해 반대 방향 전환을 만듭니다. 앞 글에서 이미 만들었다면 그 전환의 규칙 아이콘을 더블클릭해 열고, 0과 같은지 비교하던 노드를 지웁니다. 그 규칙에서는 Speed를 <=(작거나 같음) 노드로 0.1과 비교합니다. 이 예제는 같은 기준값으로 두 방향을 나누지만, 기준값 근처에서 상태가 계속 오가는 떨림을 줄이고 싶다면 진입과 복귀의 기준값을 서로 다르게 둘 수 있습니다. 규칙을 모두 만들었으면 컴파일하고 저장합니다.
상태가 늘어날 때 알아야 할 설정
스테이트 머신은 상태 수보다 전환 규칙이 많아질 때 복잡해집니다. 조건을 짧게 나누고 어느 규칙이 먼저 평가되는지 점검하면 디버깅이 쉬워집니다. 다음 설정들이 그 일을 돕습니다.
전환 블렌딩은 상태가 바뀔 때 두 애니메이션을 섞는 방식입니다. 스테이트 머신은 기본적으로 전환할 때 두 포즈를 부드럽게 섞으며, 전환 규칙 선을 선택하면 디테일 패널에서 전환에 걸리는 시간(Duration, 초 단위), 블렌드 곡선의 종류(Mode), 블렌드 방식(Blend Logic의 Standard Blend, Inertialization, Custom)을 바꿀 수 있습니다. Mode를 Custom으로 두면 Custom Blend Curve에 직접 만든 커브 에셋을 지정합니다.
전환 우선순위는 한 상태에서 나가는 전환 여러 개가 동시에 참일 때 무엇을 고를지 정합니다. 공식 문서에 따르면 이때는 Priority Order 값이 가장 작은 전환이 선택됩니다. 만든 순서에 기대지 말고 값을 직접 확인하는 습관을 들이는 것이 좋습니다. 같은 디테일 패널의 Bidirectional 항목은 공식 문서가 지원하지 않으며 동작하지 않는다고 밝히고 있으므로, 양방향 전환은 앞에서처럼 방향마다 따로 만듭니다.
콘딧(Conduit)은 여러 상태가 같은 전환 규칙을 공유할 때 그 규칙을 한곳에 모아 두는 노드입니다. 스테이트 머신 그래프에서 우클릭해 Add Conduit으로 추가하며, 공통 조건을 콘딧에 모으면 화살표 수가 줄어 그래프가 깔끔해집니다. 공식 문서에 따르면 콘딧의 규칙은 기본값이 false이므로, 만든 뒤 조건을 꼭 채워야 합니다.
캐시 포즈(cached pose)는 같은 포즈를 여러 상태나 블렌딩 로직에서 다시 쓸 때, 그 포즈를 한 번 계산해 저장해 두고 여러 곳에서 불러 쓰는 기능입니다. 같은 계산을 반복하지 않으므로 성능에 도움이 되고, 그래프도 읽기 쉬워집니다.
애님 노티파이(Anim Notify)는 애니메이션이 재생되는 도중 특정 프레임에서 이벤트를 발생시키는 기능입니다. 발소리를 재생하거나 무기의 타격 시점을 알리는 데 쓰며, 애님 블루프린트의 이벤트 그래프에서 받아 게임플레이 로직을 실행할 수 있습니다. 노티파이는 애님 몽타주와 노티파이의 기초에서 직접 만들어 봅니다.
정리
- 스테이트 머신은 캐릭터의 동작을 상태로 나누고, 상태 사이를 한 방향 전환 규칙으로 잇습니다. 두 상태를 오가려면 방향마다 전환을 하나씩 만듭니다.
- 이벤트 그래프는
Try Get Pawn Owner,Is Valid,Cast To Character,Get Velocity,Vector Length XY를 거쳐 수평 속도를Speed에 저장합니다. Idle과Walk_Run은 같은 기준값 0.1을>와<=로 나누어 쓰며, 떨림을 줄이려면 진입과 복귀 기준을 다르게 둘 수 있습니다.- 전환 블렌딩은
Duration,Mode,Blend Logic으로 조정하고, 동시에 참인 전환은Priority Order가 가장 작은 것이 선택됩니다. - 콘딧은 공통 전환 규칙을, 캐시 포즈는 반복해서 쓰는 포즈를 한곳에 모읍니다.
연습 문제
1. 기준값과 수직 이동
주어진 전환 규칙 그대로일 때, Speed가 정확히 0.1이면 Idle에서 Walk_Run으로 들어갈 수 있을까요? Walk_Run에서는 Idle로 돌아갈 수 있을까요? 또 속도가 (0, 0, 500) cm/s일 때 이 지상 Speed는 얼마일까요?
해설 보기
0.1 > 0.1은 거짓이므로 Walk_Run으로 들어가지 않습니다. 반대로 0.1 <= 0.1은 참이므로 Walk_Run에 있었다면 Idle로 돌아가는 조건을 만족합니다. 두 조건이 같은 값을 빈틈없이 나누므로, 어떤 Speed에서도 두 규칙이 동시에 참이 되지는 않습니다.
속도가 (0, 0, 500) cm/s이면 수평 성분이 모두 0이므로 Vector Length XY는 0입니다. 다만 이 두 상태만으로 캐릭터가 점프 중인지를 판정하지는 못합니다. 공중 동작이 필요하면 공중 여부를 나타내는 별도의 조건과 상태를 추가해야 합니다. 또 상태 선택 조건이 참이 된 순간과 전환 블렌드가 끝난 순간은 같은 시점이 아니라는 점도 기억해 둡니다.
2. 동시에 참이 되는 두 전환
Idle에서 나가는 전환이 두 개 있습니다. Walk_Run으로 가는 전환은 Speed > 0.1이고 Priority Order가 2이며, Jump로 가는 전환은 "공중에 있음"이 조건이고 Priority Order가 1입니다. 캐릭터가 달리면서 낭떠러지에서 떨어지는 순간 두 조건이 모두 참이라면 어느 상태로 갈까요?
해설 보기
Jump로 갑니다. 한 상태에서 나가는 전환 여러 개가 동시에 참이면 Priority Order 값이 가장 작은 전환이 선택되므로, 1인 Jump 전환이 2인 Walk_Run 전환보다 먼저입니다.
두 값을 반대로 두었다면 달리던 캐릭터가 공중에서도 Walk_Run으로 가게 됩니다. 그래서 공중 동작처럼 다른 조건보다 먼저 처리해야 하는 전환은 우선순위 값을 직접 확인해 둡니다.
3. 기준값 근처의 떨림
캐릭터가 아주 느리게 움직여 Speed가 0.1 근처에서 오르내리자, Idle과 Walk_Run이 빠르게 번갈아 바뀌며 포즈가 떨립니다. 전환 규칙을 어떻게 바꾸면 이 떨림을 줄일 수 있을까요?
해설 보기
진입과 복귀의 기준값을 서로 다르게 둡니다. 예를 들어 Idle에서 Walk_Run으로는 Speed > 10일 때 들어가고, Walk_Run에서 Idle로는 Speed <= 5일 때 돌아가게 하면, 5와 10 사이의 값에서는 지금 있는 상태가 그대로 유지됩니다.
값이 기준 근처에서 조금씩 흔들려도 두 기준 사이를 완전히 넘어가지 않는 한 상태가 바뀌지 않으므로 떨림이 줄어듭니다. 구체적인 기준값은 캐릭터의 걷기 속도와 블렌드 스페이스의 축 범위를 보고 정합니다.
전환 규칙의 디테일 패널 항목은 언리얼 엔진 공식 문서의 전환 규칙에서, 상태와 콘딧을 추가하는 방법은 스테이트 머신 문서에서 확인할 수 있습니다.
다음 글 블렌드 스페이스 기본 사용법에서는 이 글에서 쓴 BS_WalkRun처럼 속도와 방향 값으로 이동 애니메이션을 섞는 블렌드 스페이스의 축과 샘플을 설정합니다.