언리얼엔진/구현·실습

외부 캐릭터를 기존 TPS 시스템에 붙이며 겪은 리타겟팅 트러블슈팅

write76465 2026. 7. 9. 15:40

이번 작업에서는 기존 플레이어 캐릭터에 사용하던 마네퀸 기반 애니메이션 시스템을 유지하면서, 새 외형 캐릭터인 Wraith를 적용하는 작업을 진행했다.

단순히 스켈레탈 메시만 교체하면 끝날 것처럼 보였지만, 실제로는 애니메이션 리타겟팅, ABP 구조, 루트 이동, 머티리얼, 무기 메시 처리까지 여러 부분이 맞물려 있었다. 특히 이번 작업의 핵심은 “새 캐릭터가 보이게 만들기”가 아니라, 기존 이동/조준/무기 교체 시스템을 최대한 유지하면서 외형과 애니메이션만 안정적으로 교체하는 것이었다.

이미지 삽입 위치
추천 이미지: 기존 마네퀸 캐릭터와 Wraith 캐릭터를 비교한 화면. 가능하면 Content Browser에서 두 스켈레탈 메시를 나란히 보여주거나, 기존 캐릭터 BP와 새 Wraith 메시 프리뷰를 함께 캡처하면 좋다.

외부 캐릭터 메시 정리

처음 가져온 Wraith 캐릭터에는 기본적으로 캐릭터 몸체뿐 아니라 총기 메시도 포함되어 있었다. 문제는 우리 프로젝트에서는 무기를 별도 WeaponBase 액터로 관리하고 있었기 때문에, 캐릭터 메시 안에 포함된 총기가 남아 있으면 실제 장착 무기와 겹쳐 보일 수 있다는 점이었다.

처음에는 Blender로 FBX를 내보낸 뒤 총기 메시를 삭제하고 다시 Unreal에 가져오는 방식을 시도했다. 하지만 이 과정에서 머티리얼 슬롯이 깨지거나, 기존 스켈레톤 참조가 어긋나는 문제가 발생했다.

결국 메시를 직접 수정하기보다는 Unreal 안에서 총기 섹션의 머티리얼을 투명 처리하는 방식으로 정리했다. 이 방식은 원본 스켈레탈 메시 구조와 스켈레톤을 유지할 수 있어서 리타겟팅과 애니메이션 호환성 면에서 더 안정적이었다.

이번 작업에서 얻은 기준은 명확했다. 캐릭터 메시 안에 불필요한 파츠가 있더라도, 그 파츠가 스켈레톤이나 머티리얼 슬롯과 깊게 연결되어 있다면 무리하게 FBX 라운드트립을 하지 않는 편이 낫다. 특히 외부 마켓플레이스 캐릭터는 머티리얼과 LOD, 본 구조가 복잡해서 Blender를 한 번 거치는 순간 원본 참조가 깨질 가능성이 높다.

총기가 스켈레탈메쉬에 포함된 모습
블렌더를 이용해 총기 메쉬를 지우는 모습

 

블렌더에서 메쉬를 지우니 머티리얼이 밀려 깨지는 모습

IK Rig와 Retargeter 구성

Wraith 캐릭터에 기존 마네퀸 애니메이션을 사용하기 위해 IK Rig와 IK Retargeter를 구성했다.

먼저 Wraith용 IK Rig를 만들고, pelvis를 Retarget Root로 지정했다. 이후 Auto Create Retarget Chains를 사용해 기본 체인을 자동 생성했다. 기존 마네퀸 IK Rig를 Source로, Wraith IK Rig를 Target으로 지정해 RTG_Manny_To_Wraith 리타게터를 만들었다.

리타게터 프리뷰에서는 기존 마네퀸 애니메이션이 Wraith 메시 위에서 꽤 자연스럽게 재생되었다. 하지만 Export 후 실제 애니메이션 에셋으로 확인하면 프리뷰와 다른 문제가 나타났다. 대표적으로 발이 살짝 뜨거나, 이동 애니메이션에서 캐릭터가 비정상적으로 앞으로 밀리는 현상이 있었다.

이 부분에서 중요한 점은 리타게터 프리뷰가 정상이라고 해서 Export된 애니메이션까지 반드시 정상이라는 뜻은 아니라는 것이다. 프리뷰는 리타게터의 보정 상태를 보여주지만, Export된 결과물은 실제 애니메이션 에셋으로 굳어지기 때문에 루트 설정, 포즈 오프셋, Root Motion 옵션까지 별도로 확인해야 했다.



방향키 입력 시 캐릭터가 비정상적으로 밀리는 문제

Wraith 적용 후 가장 이상했던 문제 중 하나는 방향키를 눌렀을 때 캐릭터가 갑자기 앞으로 과하게 이동하는 현상이었다.

처음에는 이동 코드나 입력 값이 중복으로 들어가는 문제라고 생각했다. 하지만 기존 캐릭터에서는 같은 입력 로직이 정상적으로 동작하고 있었고, Wraith 애니메이션으로 바꿨을 때만 문제가 발생했다.

원인은 애니메이션의 루트 이동값이었다. 캐릭터 이동은 이미 CharacterMovementComponent가 처리하고 있는데, 리타겟된 애니메이션에도 루트 이동이 남아 있으면 결과적으로 캐릭터가 두 번 이동하게 된다. 즉, 코드가 한 번 밀고 애니메이션 루트가 한 번 더 밀면서 비정상적인 속도로 앞으로 튀는 것이다.

이를 확인하기 위해 문제 애니메이션의 Root Motion 관련 옵션을 점검했다. 이동용 애니메이션은 제자리 애니메이션으로 사용해야 하므로 Enable Root Motion을 끄고, 필요에 따라 Force Root Lock을 켜서 루트가 과하게 움직이지 않도록 정리했다.

이 문제를 통해 이동 시스템에서 중요한 기준을 다시 잡았다. 인게임 이동은 캐릭터 무브먼트가 담당하고, 로코모션 애니메이션은 이동감을 표현하는 역할만 해야 한다. 루트 모션을 사용할 것이 아니라면 모든 걷기/달리기 애니메이션은 제자리 기반으로 관리해야 한다.

ABP를 복사했을 때 변수 참조가 깨지는 문제

Wraith용 애니메이션 블루프린트를 만들기 위해 기존 ABP_PlayerCharacter 구조를 참고했다. 처음에는 기존 ABP를 복사해서 쓰면 빠르게 해결될 것이라 생각했지만, 실제로는 여러 변수 참조가 깨졌다.

예를 들어 기존 그래프에서는 bIsAiming, CurrentTypeWeapon 같은 이름을 참조하고 있었는데, 새 ABP에서는 실제 변수명이 IsAiming, CurrentWeaponType으로 되어 있었다. 이 때문에 Blend Poses by Bool, Blend Poses by Enum 같은 노드에서 경고가 발생했다.

또한 Event Graph에서 Cast To BP_PlayerCharacter 노드의 Object 핀이 비어 있으면, 애니메이션 인스턴스가 어떤 Pawn을 캐스팅해야 하는지 알 수 없어 컴파일 에러가 발생했다. 이 부분은 Try Get Pawn Owner의 Return Value를 Cast Object에 연결해서 해결했다.

이번에 정리한 기준은 새 ABP를 만들 때 단순 복붙보다 참조 관계 확인이 더 중요하다는 것이다. 특히 AnimGraph 안의 Blend 노드는 겉으로 보기엔 정상처럼 보여도 내부적으로 변수 경로를 들고 있기 때문에, 변수명이 바뀌면 노드가 조용히 깨질 수 있다.

 

 

 

ABP에서 캐릭터가 쪼그라드는 문제

Wraith 메시를 단독으로 열었을 때는 정상이고, 리타겟된 애니메이션도 단독 재생하면 정상인데, ABP에 넣으면 캐릭터가 쪼그라드는 문제가 있었다.

이 경우 문제를 메시나 애니메이션에서 찾기보다 ABP 그래프를 단계적으로 의심해야 했다. 실제로 AnimGraph는 여러 노드가 순서대로 포즈를 변형한다. 로코모션, Orientation Warping, Layered Blend per Bone, Slot, 조준 블렌드 등이 이어져 있기 때문에 어느 한 단계에서 포즈가 망가지면 최종 결과도 무너진다.

그래서 디버깅은 최종 Output Pose에 바로 Locomotion 캐시 포즈만 연결하는 방식으로 시작했다. 이 상태에서 정상이라면 Locomotion 자체는 문제가 없고, 그 뒤에 붙은 Orientation Warping이나 Layered Blend가 원인일 가능성이 높다. 반대로 이 상태에서도 문제가 있다면 State Machine이나 BlendSpace 안에 들어간 애니메이션 자체를 확인해야 한다.

이 방식으로 문제 범위를 좁히는 것이 중요했다. 복잡한 AnimGraph에서 모든 노드를 동시에 의심하면 원인을 찾기 어렵다. 포즈 파이프라인을 한 단계씩 복구하면서 어느 노드부터 망가지는지 확인하는 것이 가장 빠른 디버깅 방법이었다.

쪼그라들어있는 못습

Layered Blend per Bone과 상체 조준 처리

기존 캐릭터에서는 조준 상태에서 상체만 조준 자세로 바꾸고, 하체는 이동 애니메이션을 유지하는 구조를 사용했다. 이를 위해 Layered Blend per Bone을 사용했다.

하지만 캐릭터가 바뀌면서 본 구조와 체형이 달라졌기 때문에 기존 Blend Depth 값을 그대로 쓰면 어색한 결과가 나올 수 있었다. 예전에 너무 깊은 Blend Depth를 사용했을 때는 하체까지 영향을 받아 모션이 제대로 나오지 않았고, 낮은 값으로 조정했을 때 상체 분리가 더 안정적으로 동작했다.

이 작업에서 느낀 점은 Layered Blend는 단순히 “상체만 섞기” 노드가 아니라, 정확히 어느 본부터 얼마나 깊게 영향을 줄지 결정하는 매우 민감한 설정이라는 것이다. 캐릭터 메시가 바뀌면 같은 ABP 구조를 쓰더라도 본 이름과 Blend Depth를 다시 확인해야 한다.

 

Retarget Pose 보정

Wraith는 마네퀸과 팔 벌림 각도나 어깨 위치가 완전히 같지 않았다. 이 차이는 정지 상태에서는 작아 보여도, 조준이나 무기 들기 애니메이션에서는 손 위치와 상체 각도 차이로 크게 드러날 수 있다.

이를 해결하기 위해 Retarget Pose를 사용했다. Source와 Target의 기준 포즈를 최대한 맞춘 뒤 애니메이션을 다시 Export하는 방식이다. 특히 팔 각도, 어깨 높이, 손목 방향은 총기 애니메이션에서 매우 민감하게 작용한다.

처음에는 리타겟 결과가 어느 정도 괜찮아 보여서 그냥 넘어갈 수도 있었지만, 실제 무기 장착과 조준까지 연결하면 작은 포즈 차이가 계속 누적된다. 결국 외형 캐릭터를 바꿀 때는 단순히 “움직인다” 수준에서 끝내지 않고, 무기와 손 위치까지 고려한 기준 포즈 보정이 필요했다.

 

원래 팔 각도
맞춘 후 팔 각도

 

Export 후 발이 뜨는 문제

리타게터 프리뷰에서는 발이 바닥에 잘 붙어 있는데, Export한 애니메이션에서는 발이 살짝 뜨는 문제가 있었다.

이 문제는 리타게터의 Root Settings, Export 결과물의 Root Motion 설정, 애니메이션 에셋의 루트 잠금 옵션을 함께 봐야 했다. 프리뷰에서 정상이라고 해서 애니메이션 에셋에서도 같은 결과가 보장되지 않았기 때문이다.

우선 Export된 애니메이션에서 Root Motion 관련 옵션을 확인했다. 이동용 로코모션에서는 루트 모션을 사용하지 않기 때문에 Enable Root Motion은 끄고, 루트 위치가 흔들리지 않게 Force Root Lock을 확인했다. 그래도 발이 떠 있다면 Retargeter의 Root Settings에서 Z Offset을 약간 조정한 뒤 다시 Export하는 방식으로 접근했다.

이 문제는 겉으로 보기에는 단순한 위치 오차지만, 실제로는 캐릭터 높이, 루트 본, pelvis 위치, 리타겟 포즈가 모두 영향을 주는 문제였다. 그래서 한 애니메이션만 임시로 내리는 것보다 리타게터 단계에서 기준을 맞추는 쪽이 더 유지보수하기 좋다.

 

발이 떠 있는 모습

 

 

기존 시스템을 유지하면서 새 캐릭터를 붙이는 기준

이번 작업의 핵심은 Wraith 캐릭터를 새로 만드는 것이 아니라, 기존 플레이어 시스템 위에 외형과 애니메이션을 교체하는 것이었다.

그래서 C++의 이동, 조준, 무기 교체, 사격 시스템은 그대로 유지하고, ABP와 애니메이션 에셋만 Wraith 기준으로 교체하는 방향을 잡았다. 이 방식은 처음에는 설정할 것이 많지만, 한 번 구조가 잡히면 이후 다른 캐릭터를 추가할 때도 같은 방식으로 확장할 수 있다.

특히 AnimInstance 부모 클래스를 유지한 것이 중요했다. PlayerCharacterAnimInstance에서 계산하는 Speed, Direction, IsAiming, CurrentWeaponType 같은 값은 그대로 사용하고, ABP 쪽에서는 그 값을 받아 Wraith 전용 애니메이션으로 표현만 바꾸는 구조가 된다.

즉, 게임 로직과 표현 레이어를 분리하는 방향이다. 캐릭터가 바뀌어도 입력과 전투 로직은 유지되고, 메시와 애니메이션만 교체할 수 있는 구조가 된다.

마무리

이번 작업은 외형 캐릭터 하나를 바꾸는 것처럼 보였지만, 실제로는 리타겟팅 파이프라인과 ABP 구조를 다시 점검하는 작업에 가까웠다.

특히 기억에 남는 문제는 방향키 입력 시 캐릭터가 비정상적으로 앞으로 밀리는 현상이었다. 처음에는 입력이나 이동 코드 문제처럼 보였지만, 실제 원인은 리타겟된 애니메이션에 남아 있던 루트 이동값이었다. 이처럼 애니메이션 시스템에서는 코드 문제가 아닌데도 코드 문제처럼 보이는 현상이 자주 발생한다.

또한 ABP에서 캐릭터가 쪼그라드는 문제는 그래프를 한 번에 고치려 하지 않고, Locomotion만 Output에 연결하는 방식으로 단계별로 원인을 좁혀 갔다. 이 과정에서 AnimGraph는 단순한 노드 연결이 아니라 포즈가 순서대로 가공되는 파이프라인이라는 점을 다시 체감했다.

결과적으로 이번 작업을 통해 외부 캐릭터를 프로젝트에 적용할 때 확인해야 할 기준이 정리되었다. 메시를 무리하게 수정하기보다 원본 구조를 유지하고, 리타겟 포즈와 루트 설정을 먼저 맞추며, ABP는 노드 단위로 문제 범위를 좁혀 가는 방식이 가장 안정적이었다.