TECHARTNOMAD | MAZELINE.TECH

TECH.ART.FLOW.IO

[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 8방향 이동

jplee 2026. 7. 22. 00:51

저자: DarkFlameMaster

최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한다.

1. 간단한 소개와 사고 정리

8방향 이동이란, 캐릭터가 앞, 뒤, 좌, 우, 좌전방, 좌후방, 우전방, 우후방으로 이동하는 애니메이션을 갖는 것을 말한다. 캐릭터의 컨트롤러 회전(컨트롤러 회전은 특정 방향을 가리키는 단위 벡터라고 대략 이해해도 된다)과 캐릭터의 속도 벡터 사이에 일정한 크기의 각도가 생기면, 캐릭터의 애니메이션도 그에 맞춰 변화해야 한다.

예를 두 개 들어보자. 하나는 속도 방향은 변하지 않고 컨트롤러 방향만 회전하는 경우다. 예를 들어 현재 캐릭터가 우리가 “W”를 누르고 있을 때 x축(월드 좌표계 기준)을 따라 직선으로 앞으로 달리고 있다고 하자. 이때 마우스를 회전시켜 컨트롤러가 오른쪽으로 돌아 y축(월드 좌표계 기준)을 향하게 만들면, 캐릭터는 오른쪽 앞방향으로 달리는 동작을 해야 자연스럽게 보인다. (이때 W는 계속 누르고 있다.)

너 뭘 봐?

너 뭘 봐?

다른 예는 컨트롤러 방향은 변하지 않고 속도 방향이 바뀌는 경우다. 마찬가지로 현재 캐릭터가 우리가 “W”를 누르고 있을 때 x축(월드 좌표계 기준)을 따라 직선으로 앞으로 달리고 있다고 하자. 이때 “W”를 계속 누른 상태에서 “D”를 동시에 누르고, 마우스는 움직이지 않는다. 그러면 캐릭터 역시 오른쪽 앞방향으로 달리는 동작을 해야 자연스럽게 보인다.

이 두 예시에서 캐릭터의 달리기 애니메이션이 정면에서 우전방으로 바뀌는 원인은 모두 같다. 컨트롤러와 속도 방향의 변화가 컨트롤러와 속도 사이 각도를 바꾸기 때문이다. 그래서 우리는 이 변화를 드러내기 위해 애니메이션을 변경해야 한다.

그러므로 8방향 이동을 구현하려면 해야 할 일은 꽤 명확하다. 매 프레임마다 캐릭터 속도와 컨트롤러 회전 사이의 각도를 계산하고, 그것으로 애니메이션을 갱신하면 된다.

2. 전통적인 방법과 그 문제점

캐릭터 속도와 컨트롤러 회전 사이의 각도는 아래 노드로 계산할 수 있다.

UE, 정말 친절하다. 손잡고 애니메이션 만들라고 가르쳐주는 수준이다.

UE, 정말 친절하다. 손잡고 애니메이션 만들라고 가르쳐주는 수준이다.

각도가 연속적으로 변화하는 문제이기 때문에, 자연스러운 생각은 블렌드 스페이스를 사용하는 것이다. 하나의 좌표축을 -180~180도로 설정하고, 그 안에 8방향 이동의 각 애니메이션을 배치하는 방식이다.

(Advanced Locomotion System 4에는 정우측과 정좌측 애니메이션이 별도로 제작되어 있지 않기 때문에, 여기서는 애니메이션 시퀀스 두 개를 덜 넣고 대충 맞춰두었다.)

정확히 말하면 ALS4에는 우전방과 좌전방 애니메이션이 제작되어 있지 않다. 우전방과 좌전방이라는 이름을 달고 있는 애니메이션 시퀀스 안에는 실제로 정우측과 정좌측 애니메이션이 들어 있다. 우전방과 좌전방 애니메이션 효과를 만들려면 직접 수동으로 블렌드해야 한다. 우후방과 좌후방도 보기에는 그냥 역재생한 결과처럼 보인다.

정확히 말하면 ALS4에는 우전방과 좌전방 애니메이션이 제작되어 있지 않다. 우전방과 좌전방이라는 이름을 달고 있는 애니메이션 시퀀스 안에는 실제로 정우측과 정좌측 애니메이션이 들어 있다. 우전방과 좌전방 애니메이션 효과를 만들려면 직접 수동으로 블렌드해야 한다. 우후방과 좌후방도 보기에는 그냥 역재생한 결과처럼 보인다.

이 생각은 매우 자연스럽다. 하지만 블렌드 스페이스 자체의 성질 때문에, 이方案은 실행할 수 없다.

간단히 말하면 문제는 “점프”에 있다. 예를 들어 왼쪽에서 오른쪽으로 갈 때 값이 점프한다. (오른쪽에서 왼쪽으로 가도 마찬가지다.) 이 문제는 조금 작은 편이다. 이유는 180도만 점프하기 때문이다. 블렌드 시간을 조심스럽게 선택하면 억지로 해결할 수도 있다. 블렌드 시간이 짧으면 점프할 때 동작이 빠르게 전환되며 생기는 변형이 더 뚜렷해지고, 블렌드 시간이 길면 캐릭터가 좌우를 전환할 때 중간에 정면을 향해 “제자리걸음”하는 두 스텝이 나타난다.

더 심각한 문제는 좌후방에서 우후방으로 갈 때의 점프다. (우후방에서 좌후방도 마찬가지로 점프한다.) 얼핏 보면 좌후방과 우후방 두 동작의 차이는 그렇게 크지 않아 보이고, 원래라면 블렌드해도 자연스러워야 할 것 같다.

하지만 블렌드 스페이스의 눈에는 좌후방과 우후방 두 동작을 블렌드하는 것이 아니다. 좌표축 맨 왼쪽 끝에 있는 애니메이션을 좌표축 맨 오른쪽 끝에 있는 애니메이션으로 블렌드하는 것이다.

블렌드 스페이스는 사용자가 정한 블렌드 시간 안에 좌표축 위의 애니메이션을 하나씩 차례로 섞어 지나간다. 그래서 최종적으로 실제 보이는 효과는, 캐릭터가 뒤로 이동할 때마다 마우스를 좌우로 조금만 움직여도 캐릭터가 한 번씩 경련하는 것처럼 보이는 것이다. 극도로 부자연스럽다. (축을 -180~180에서 0~360으로 바꿔도 소용없다. 그렇게 하면 떨림이 뒤로 걸을 때가 아니라 앞으로 걸을 때 생길 뿐이다.)

블렌드 스페이스가 “원형” 수직선을 지원할 수 있다면 좋았을 것이다. 아쉽게도 현재는 지원하지 않고, 직선 축만 처리할 수 있다. 그래서 우리는 상태 머신을 사용해 점프 문제를 해결할 수밖에 없다.

3. ALS4가 애니메이션 상태 머신으로 8방향 이동을 구현하는 방식

3.1 이동 의도 계산

전통적인 방법에서는 캐릭터 속도와 컨트롤러 사이의 각도가 얼마인지에 따라 그에 대응하는 이동 애니메이션을 사용한다. 하지만 애니메이션 상태 머신에서는 점프로 인한 부자연스러움을 극복해야 하므로, 이렇게 직접적인 방식을 사용할 수 없다.

우리는 각도의 구간을 직접 “어느 애니메이션을 사용할지”로 대표시킬 수 없다. 이 각도는 오직 **“이동 의도”**를 표현하는 데만 쓰인다. 구체적으로 어떤 애니메이션 시퀀스를 사용할지는 이동 의도와 캐릭터가 현재 사용 중인 애니메이션 시퀀스를 종합해서 결정해야 한다.

이동 의도: 앞, 뒤, 왼쪽, 오른쪽 네 방향만 있다. 캐릭터의 속도 방향과 컨트롤러 회전 사이의 각도로 계산한다. 우리는 컨트롤러와 캐릭터 속도 방향의 각도가 -70~70도이면 앞, 70~110도이면 오른쪽, -70~-110도이면 왼쪽, 나머지는 뒤라고 규정한다.

분명히 이동 의도는 월드 좌표계와는 관계가 없고, 플레이어 자신의 좌표계와만 관련이 있다. 우리는 각도가 앞/뒤/좌/우 네 구간(혹은 사분면) 중 어디에 있는지 판단하는 함수를 작성할 수 있다.

함수 핵심 내용의 스크린샷

함수 핵심 내용의 스크린샷

버퍼라는 이 파라미터는 사분면의 범위를 동적으로 확대하거나 축소하는 데 사용된다. 캐릭터의 현재 이동 의도가 왼쪽 또는 오른쪽일 때에는 앞뒤 각도 구간을 확대하고, 좌우 사분면의 각도 구간을 축소한다. 반대로도 마찬가지다.

캐릭터 컨트롤러와 캐릭터 속도의 각도를 계산해 사분면 함수에 넣으면, 캐릭터의 다음 이동 의도를 얻을 수 있다. 이 각도를 어떻게 계산하느냐에 대해서, ALS4에서는 이렇게 한다. (AimingRotation은 캐릭터 컨트롤러 회전을 저장한다.)

하지만 앞에서도 말했듯이, UE에는 편리한 내장 함수(방향 계산)가 있다.

이 두 방식의 효과는 동등하다. 독자는 직접 실험해서 검증해봐도 된다.

3.2 8방향 이동 애니메이션 상태 머신 제작

그림에서 보듯, 모든 노란색 전이 조건은 “이동 의도 == 앞으로”, 초록색 전이 조건은 “이동 의도 == 뒤로”, 빨간색은 오른쪽, 파란색은 왼쪽이다. (같은 색을 가진 것은 공유 전이 규칙을 사용했기 때문이다.)

이 상태 머신은 전통적인 블렌드 스페이스 방법에서 발생하는 점프 문제를 해결한다. 이 상태 머신을 구성하는 사고방식을 간단히 말해보자.

바깥쪽의 이 빨간 원은 이해하기 쉬울 것이다. W를 누르고, WD, D, SD, S라는 키 입력 순서로 가면, Move-F, Move-FR, Move-BR, Move-B 상태 노드로 이동할 수 있다. 만약 W를 누른 상태에서 바로 S를 누르는 상태로 바뀐다면, 가운데 빨간 지름을 따라 Move-F에서 Move-B로 바로 변한다.

우리는 중간의 두 주황색 전이 조건의 의도를 중점적으로 이야기해보자.

블렌드 스페이스에서 우전방에서 좌후방으로 전환하려면, 180도 점프가 발생하기 때문에 좌표축 절반에 해당하는 애니메이션 시퀀스를 쭉 블렌드해서 지나가야 한다. (이 상태 머신에 놓고 보면 빨간 원주를 따라 반 바퀴 도는 것으로 나타난다.) 그러면 그다지 자연스럽지 않아 보인다. 그래서 우전방과 좌후방 애니메이션이 “원주를 반 바퀴 도는” 과정 없이 직접 블렌드될 수 있도록, 특별히 이 주황색 지름을 추가했다. 180도 점프가 발생할 때 목표 애니메이션과 직접 블렌드할 수 있게 한 것이다.

자세히 관찰하면, 이 상태 머신에는 총 세 개의 지름이 있다. 모두 180도 점프 시의 블렌드를 처리하기 위해 설계된 것이다.

그렇다면 360도 점프는? 애니메이션 상태 머신 안의 상태 노드는 고리 형태로 연결될 수 있기 때문에, 이 문제는 저절로 해결된다.

또 하나 말할 만한 점은, 8방향 이동 애니메이션 상태 머신인데 상태 노드는 6개밖에 없다는 것이다. 하지만 이것은 영향을 주지 않는다. 8개 상태 노드(실제로는 10개여야 한다. 정좌측과 정우측은 사실 정방향으로 걷는지 후방으로 걷는지, 혹은 가슴 방향과 이동 방향이 일치하는지에 따라 나눠야 한다)로 만드는 것도 가능하다. 다만 그러려면 이동 의도 계산에 더 많은 공을 들여야 한다. 이동 의도는 앞/뒤/좌/우 네 개의 열거값만으로는 부족하고, 실제로 확실한 8방향 열거값이 필요하다. 당연히 판단도 더 번거로워진다. 상태 머신 안의 전이 조건도 원래 4개 그룹에서 8개 그룹으로 나뉘게 된다. 연결 사고방식은 위와 비슷하니, 관심 있는 독자는 직접 한번 시도해봐도 된다.

그럼 왜 이런 6개 상태 노드짜리 8방향 이동 상태 머신도 정상적으로 동작할 수 있는가?

앞에서 언급했듯, ALS 시스템의 우전방 애니메이션은 이름만 우전방일 뿐이다. 실제로 들어 있는 것은 가슴이 오른쪽을 향한, 정우측 이동 애니메이션이다. (캐릭터는 이때 정방향으로 걷고 있다.)

그리고 우후방 애니메이션은 등이 오른쪽을 향한, 정우측 이동 애니메이션이다. (맞다. 아무리 봐도 가슴이 왼쪽을 향한 좌측 이동 애니메이션을 역순 재생한 것처럼 보인다 = = 캐릭터는 이때 뒤로 걷고 있다.)

ALS4의 관점에서 우전방은 “오른쪽 앞방향으로 이동”이 아니라, 가슴(몸의 앞면)이 오른쪽을 향한 채 오른쪽으로 이동하는 것이다. 마찬가지로 우후방도 등(몸의 뒷면)이 오른쪽을 향한 채 오른쪽으로 이동하는 것이다.

따라서 이 6개 상태 노드짜리 상태 머신은, 겉으로 보기에는 “정좌측과 정우측”이 없는 것 같지만, 실제로는 오직 “정좌측과 정우측”만 있고 좌전방/좌후방/우전방/우후방이 없는 셈이다.

먼저 W를 누르고, W를 놓은 뒤 A를 누르면 FL 노드에 도달한다. 이때는 “몸의 앞방향이 왼쪽”인 정좌측 이동 상태다. 여기서 다시 A를 놓고 D를 누르면, 주황색 지름을 따라 BR 노드로 가게 된다. 즉 “몸의 앞방향이 왼쪽”인 정우측 이동이다.

이것은 이런 설계의 장점 중 하나를 보여준다. 좌우 전환처럼 격렬한 180도 점프가 있을 때, 캐릭터의 가슴 방향은 변하지 않는다. 캐릭터 가슴이 180도 돌아버리는 상황이 발생하지 않는다.

어떤 독자는 묻고 싶을 것이다. 그럼 약속했던 우전방/우후방, 좌전방/좌후방은 어디 갔는가? 답은 Move-F 또는 Move-B 노드 안에서 블렌드해서 얻는다는 것이다. 구체적으로 어떻게 블렌드하고, 사용되는 블렌드 값은 어떻게 계산해야 하는지는 다음 절에서 말하겠다.

3.3 속도 블렌드 값 계산

이동 의도가 해결하는 문제는 상태 노드 사이의 전환이고, 속도 블렌드 값이 해결하는 문제는 상태 노드 내부의 애니메이션 블렌드다.

속도 블렌드 값을 계산할 때는 주로 캐릭터의 상대 속도를 사용한다. 이 개념은 이동 의도와 구분할 필요가 있다. 캐릭터의 상대 속도란 현재 시점에서 캐릭터 자신의 좌표계 기준 이동 방향을 뜻하고, 이동 의도는 캐릭터가 다음 시점에 향하려는 이동 방향을 뜻한다.

또한 이동 의도는 앞/뒤/좌/우 네 값으로만 나뉘기 때문에, 속도 블렌드 값이 요구하는 정밀한 블렌드를 구현할 수 없다.

속도 블렌드 값은 사실상 캐릭터의 상대 속도를 캐릭터 좌표계의 X/Y축에 직교 분해하여, 캐릭터 상대 속도가 X축과 Y축에서 가지는 성분을 얻는 것이다. 캐릭터 좌표계의 X/Y축은 실제로 앞/뒤/좌/우를 뜻하므로, 이 성분은 캐릭터가 현재 왼쪽(오른쪽)으로 이동하는 정도와 앞(뒤)으로 이동하는 정도를 나타낸다.

상대 속도의 x 성분과 y 성분을 (x^2 + y^2)의 제곱근으로 나누어, 상대 X와 상대 Y에 할당한다.

이렇게 하면 속도 블렌드 값 계산은 완료된다.

그리고 속도 블렌드 값에 보간을 적용하는 함수도 하나 더 작성해야 한다. 캐릭터 이동 상태가 변화할 때 부드럽게 전환되도록 하기 위해서다. 원본 속도 블렌드 값은 이전 프레임의 옛 데이터이고, 목표 속도 블렌드 값은 이번 프레임의 새 데이터다.

아래는 상태 노드 안에서의 활용이다.

캐릭터의 앞, 뒤, 좌전방, 우전방 애니메이션을 멀티 핀 블렌드한다. 여기서는 캐시 포즈를 사용해 애니메이션 시퀀스를 “변수”처럼 저장했다. 이렇게 하면 애니메이션 시퀀스를 교체할 때 애니메이션 상태 머신을 수정할 필요가 없다. 전달되는 포즈만 바꾸면 된다.

그런데 FR 노드에서는 Left 방향의 애니메이션에 LF를 사용할 수 없고, LB를 사용해야 한다. 이유는 위에서 말한 것처럼, 좌우 180도 점프 시에는 가슴 방향이 변하지 않기를 원하기 때문이다. 따라서 LB 애니메이션(즉 뒤로 걷기, 가슴이 오른쪽을 향한 채 왼쪽으로 이동하는 애니메이션)을 사용해야 한다.

마찬가지로 BL 노드에서도 위 그림과 완전히 똑같다.

FL과 BR 노드에서는 이런 모습이다.

Move-B 노드에서는 L과 R의 애니메이션 포즈에 LB와 RB를 사용한다.

FR 노드에서 BL 노드로 점프하는 예를 들어 이 상태 머신의 블렌드를 설명해보자.

캐릭터 이동 상태가 바뀌는 순간, 이동 의도는 즉시 변화하고 상태 머신은 FR 노드에서 BL 노드로 이동한다. 전이 조건은 자동으로 두 노드의 출력 포즈를 블렌드한다. 그런데 속도 블렌드에는 보간을 사용했기 때문에, 상태 머신은 이미 상태 노드 점프를 했더라도 속도 블렌드 자체는 아직 균일하게 변화하는 중이다. (이때 R은 아직 0으로 내려가지 않았고, L도 아직 1로 올라가지 않았다.)

FR 노드와 BL 노드에서 사용하는 포즈는 완전히 동일하며, 점프가 발생한 순간 속도 블렌드 값도 아직 크게 변하지 않았다. 그래서 이때 BL 노드의 출력 포즈는 사실 FR 노드와 별 차이가 없다. 바꿔 말하면, 전이 조건이 블렌드해야 하는 두 상태 노드의 출력 포즈가 매우 비슷하므로, 블렌드 결과도 비교적 자연스럽다.

그 후 BL 노드 내부에서 속도 블렌드의 보간이 진행되면서, BL 노드의 출력 포즈도 점차 가슴이 오른쪽을 향한 우측 이동 애니메이션에서 가슴이 오른쪽을 향한 좌측 이동 애니메이션으로 전환된다.

이렇게 해서 한 번의 자연스럽고 균일한 동작 전환이 완료된다. (사실 이렇게 해도 아직 충분히 자연스럽지는 않고, 해야 할 다른 작업이 좀 더 있다. 하지만 일단 여기까지 업데이트하고, 남은 것은 나중에 다시 이야기하자 = =)

또한 위에서 말하지 않은 것은 캐시 포즈에 입력되는 포즈가 어떤 모습이어야 하는가다. 여기서 간단히 한마디 하자면, 애니메이션 시퀀스를 직접 사용해도 물론 가능하지만, 우리가 「UE4/UE5 골격 애니메이션 고급 로코모션 시스템: 걷기/달리기 블렌드 기초 - 知乎 (zhihu.com)」에서 언급한 방식을 사용하는 것이 좋다.

관심 있는 독자는 한번 가서 읽어봐도 된다.

맺음말

이 글은 필자가 @五谷延年 선배가 B站( 빌리 빌리를 말함 )(그리고 冲呀 플랫폼)에 올린 고급 로코모션 시스템 튜토리얼을 공부하는 과정에서, 튜토리얼에 약간 부족한 점이 있다고 느꼈고, 그 때문에 공부할 때 적지 않은 혼란이 있었던 데서 출발했다.

물론 필자는 튜토리얼을 모든 면에서 빠짐없이 만들려면 마음도 힘도 많이 들 뿐 아니라 현실적으로 어렵다는 것을 잘 알고 있다. 필자는 五谷延年 선배가 UE 커뮤니티에 사심 없이 기여한 이 튜토리얼에 매우 감사하고 있으며, 무슨 불평을 하려는 것도 아니다. 그래서 이 글을 썼다. 어디까지나 五谷延年 선배 튜토리얼에 대한 아주 작은 보충이라고 보면 된다.

여기까지 본 독자는 가능하다면 손 가는 김에 좋아요와 즐겨찾기(그리고 가능하면 좋아요 버튼도 하나 더)를 눌러주면 좋겠다. 이건 나에게 정말 중요하다 = =! 앞으로도 골격 애니메이션 관련 튜토리얼과 생각 공유가 더 있을 예정이니, 팔로우해두면 업데이트를 놓치지 않을 수 있다.

마지막으로, 중간고사와 수업 실험이 가까워지고 있어서, 최근에는 글을 업데이트할 시간이 아마 없을 것이다…… (좋아요와 댓글로 업데이트를 재촉할 수는 있다)

그럼 우리는, 다음에 또 만나자!

덧붙여 여기서 필자가 막 만든 UE 골격 애니메이션 교류방을 살짝 광고한다. 916274600 각위 大佬들의 매서운 지적을 환영합니다.

참고:

【초보자용】언리얼 4 ARPG 튜토리얼 - 리셋판 - 7화 - 활 사용 시 8방향 이동 상태_哔哩哔哩_bilibiliwww.bilibili.com/video/av80124207/

언리얼 4(UE4) 애니메이션 기술: 쉽게 깊이 들어가는 고급 로코모션 시스템_哔哩哔哩_bilibiliwww.bilibili.com/video/BV12f4y1r71N

너와 처음 만났던 그날의 일

아이라, 나의 아이라 으흐흑

아이라, 나의 아이라 으흐흑