2026. 5. 30. 01:10ㆍUnreal

캐릭터 에셋을 받아오고 보니, 캐릭터의 발이 캡슐 컴포넌트에 의해서 공중에 붕 떠있는 모습을 볼 수 있었다.
언리얼 기본 캐릭터를 사용하면 기본 캐릭터로 만들어진 IK Rig가 있어 그걸 사용하면 되지만 다른 에셋에 있는 스켈레톤을 사용하면 새로 IK Rig를 만들어야 한다.
이 부분을 한 번 해보려고 한다.
참고 블로그 : https://tartist.tistory.com/160
IK RIG란?
IK Rig는 스켈레탈 메시의 뼈대에 역운동학 솔버를 정의하는 에셋이다. 런타임에 목표 위치(Goal)를기반으로 뼈대의 Transform을 역산하여 애니메이션을 보정한다.
순운동학 vs 역운동학
FK(Forward Kinematics)는 부모 뼈의 로컬 회전값이 자식 뼈로 전파되는 방식이다.
Hips → LeftUpLeg → LeftLeg → LeftFoot
각 뼈의 Rotation이 Transform 계층을 따라 전달
IK(Inverse Kinematics)는 End Effector(체인의 끝 뼈)의 월드 위치를 목표값으로 받아 체인 전체의 회전값을 역산한다.
목표 위치(Goal) → LeftFoot이 Goal에 닿으려면?
→ LeftLeg Rotation 역산
→ LeftUpLeg Rotation 역산
IK Rig 적용 과정
1. IK Rig 생성

IK Rig를 생성하고자 하는 Skeletal Mesh에 우클릭해서 Create → IK Rig 를 클릭한다.

그 후 IK Rig를 열고 Spine( 몸의 중심 부분 )에 우클릭 후 New IK Goal으로 IK Goal을 선택하면 다음과 같이 생성된다.


그 후 Set Root Bone on Selected Solver를 클릭해서 Root로 만들어준다.
2. IK Rig 세팅 시작

먼저 계산이 시작될 다리의 부분을 선택해서 Add Settings to Selected Bone을 클릭한다.

그 후에 발 부분에 IK Goal을 눌러주면 된다.
이를 양쪽에 진행한다.
블루프린트 설정
먼저 바닥에 라인 트레이스를 쏴서 바닥에 닿아있는지 계산해야한다.
1. Anim Graph에 IK Rig 연결


IK Rig를 연결하고, 디테일 창에서 아까 만든 IK Rig를 연결한다.
2. FootTrace 함수
입력값을 FootLocation(발 소켓 위치)과 RootLocation(루트 소켓 위치)을 받아서 Offset과 FootRotation을 반환하는 함수이다.
트레이스 범위 설정

발의 X, Y좌표는 그대로 사용하고 Z만 루트 기준으로 위아래를 설정한다.
Start : (FootX, FootY, RootZ + 30) ← 발 위에서 시작
End : (FootX, FootY, RootZ - 50) ← 발 아래까지 탐색
Offset 계산

히트가 발생하면 ImpactPoint.Z에서 RootLocation.Z를 빼서 발이 얼마나 올라가야 하는지 계산한다.
hit -> Offset = (0, 0, ImpactPoint.Z - RootZ)
miss -> Offset = (0, 0, 0)
FootRotation 계산

지면 법선 벡터(Normal)를 분해해서 발이 바닥 경사에 맞게 회전하도록 Rotator를 만든다.
DegAtan2(Normal.Z, Normal.Y) -> Roll
DegAtan2(Normal.Z, Normal.X) * -1 -> Pitch
MakeRotator(Roll, Pitch, 0) -> FootRotation
hit가 아니면 (0, 0, 0)을 반환한다.
3. Event Graph - 발 위치 계산
캐릭터 레퍼런스 가져오기

Blueprint Update Animation 이벤트에서 시작한다.
TryGetPawnOwner로 폰을 가져온 뒤 PlayerCharacter를 Cast해서 캐릭터 레퍼런스를 확보한다.
공중 여부 판단


CharacterMovement에서 IsFalling, IsFlying, GetLastUpdateVelocity의 Z값이 0이 아닌지를 OR연산으로 묶는다.
셋 중 하나라도 True이면 캐릭터가 지면에서 떨어져 있다고 판단한다.
공중일 때는 LeftFootOffset, RightFootOffset, LeftFootRotation, RightFootRotation을 전부 기본값(0)으로 세트해서 IK가 적용되지 않도록 한다.
FootTrace 호출

지면에 있을 때는 Mesh의 소켓 위치를 가져와서 FootTrace를 호출한다.
GetSocketLocation("LeftFoot") → FootTrace의 FootLocation 입력
GetSocketLocation("root") → FootTrace의 RootLocation 입력
GetSocketLocation("RightFoot") → 오른발도 동일하게 처리
보간 처리

FootTrace에서 받은 Offset과 Rotation을 바로 세트하지 않고 VInterpTo, RInterpTo로 부드럽게 보간한다.
InterpSpeed는 10정도로 설정했다. 갑작스러운 발 위치 변화를 방지하기 위해서이다.
LeftFootOffset.Z > RightFootOffset.Z -> SelectVector로 높은 쪽 선택
-> Z값을 3.2로 나눈 뒤 더해서 SpineOffset 계산
4. Animation Graph - IK 적용
포즈 흐름


IK Rig 노드는 Local Space 포즈를 입력으로 받는다. 그런데 ModifyBone은 Component Space에서만 동작한다. 그래서 두 노드 사이에 LocalToComponentSpace 변환이 하나 더 들어가는 것이다.
IK Rig 앞에 Local → Component → Local이 있는 것도 같은 이유다. 앞 단계에서 넘어오는 포즈가 Component Space 상태일 수 있기 때문에 IK Rig에 넣기 전에 명시적으로 Local Space로 맞춰주는 것이다.
결국 각 노드가 요구하는 포즈 공간이 다르기 때문에 변환 노드를 중간중간 끼워넣어서 맞춰줘야 한다. 순서를 틀리면 IK가 엉뚱한 공간에서 계산되어 발이 이상한 위치로 가게 된다.
IK Rig 노드
Event Graph에서 계산한 변수를 Goal위치로 연결한다.
| Goal | 연결 변수 |
| LeftFoot_Goal_Position | LeftFootOffset |
| RightFoot_Goal_Position | RightFootOffset |
| Spine_Goal_Position | SpineOffset |
Position Alpha는 모두 1.0으로 설정해서 IK가 100% 적용된다.
Modify Bone
IK Rig로 위치를 보정한 뒤 ModifyBone으로 발 회전까지 적용한다.
LeftFootRotation과 RightFootRotation의 Roll, Pitch를 0.1을 곱해서 Addtive 방식으로 적용한다.
적용

이제 캐릭터 애니메이션 그래프를 열어 아까 만든 애니메이션 블루프린트를 Output Pose와 Control Rig 사이에 넣고 실행해보면

정상적으로 바닥에 붙어있는 것을 확인할 수 있다.
핵심포인트
1. 외부 에셋 스켈레톤은 IK Rig를 직접 만들어야 한다. 언리얼 기본 캐릭터에는 IK RIg가 내장되어 있지만 Mixamo 등 외부 에셋은 직접 생성하고 체인과 Goal을 설정해야 한다.
2. 발 위치 보정은 소켓 기준으로 트레이스를 쏴서 계산한다. FootLocation의 X, Y는 그대로 유지하고, Z만 지면 ImpactPoint 기준으로 보정한다.
3. 공중에 있을 때는 IK를 비활성화해야 한다. IsFalling, IsFlying, VelocityZ 세 가지를 OR로 묶어서 하나라도 true이면 오프셋을 0으로 초기화 한다.
4. 보간 없이 바로 적용하면 발이 튄다. VInterpTo, RInterpTo로 부드럽게 보간해야 자연스러운 발착지가 구현된다.
5. Anim Graph에서 포즈 공간 변환 순서가 중요하다. IK Rig는 Component Space에서 동작하므로 LocalToComponentSpace로 변환 후 적용하고 다시 ComponentToLocalSpace로 되돌려야 한다.
6. Modify Bone으로 발 회전을 Additive로 추가한다. 지면 법선에서 DegAtan2로 계산한 Roll, Pitch를 기존 애니메이션에 더하는 방식으로 경사먼에서 발이 자연스럽게 기울어진다.
'Unreal' 카테고리의 다른 글
| <Unreal> 모듈 & 플러그인 만들기 (0) | 2026.06.23 |
|---|---|
| <언리얼> 애니메이션 리타겟팅(UE5) (0) | 2026.05.17 |
| <언리얼 C++> RandRange와 VRandCone의 차이 (0) | 2026.05.07 |
| < UE5 > 레벨 진행 시스템 - GameStateClass (1) | 2026.04.28 |
| < 언리얼 C++ > 6자유도 비행체 + 중력 / 낙하 + 에어 컨트롤 구현 (0) | 2026.04.22 |