TECHARTNOMAD | MAZELINE.TECH

TECH.ART.FLOW.IO

[번역] UE4 UE5 스켈레탈 애니메이션 고급 로코모션 시스템 손 IK 가상 뼈

jplee 2026. 7. 28. 13:14

저자: DarkFlameMaster

최근 언리얼 엔진의 스켈레탈 애니메이션 관련 지식을 공부하고 있는데, 가르치면서 배운다는 마음으로 여기에 애니메이션 관련 글을 써 보면서 배운 걸 바로바로 풀어내 보려 한다.

(이 글에서는 대화형 글쓰기를 시도해 보았다. 독자가 읽는 재미도, 내가 쓰는 재미도 살려 보고 싶어서 《중2병이라도 사랑이 하고 싶어!》의 두 주인공 입을 빌렸다. 앞부분에 짧은 배경 설정이 있으니, 후기를 먼저 읽어 보길 추천한다.

1.서막

일요일 오후, 따스한 햇살이 창밖 나뭇잎 사이로 스며들어 아파트 베란다 위에 금빛 깃털처럼 흩뿌려진다. 베란다 문을 열면 졸졸 흐르는 물소리가 들리고, 손바닥을 들어 올리면 강가에서 불어오는 촉촉하고 서늘한 바람이 스친다.

시가현의 이 작은 아파트 안에서, 언리얼 엔진을 가르치는 은행학원에 다니는 소년과 소녀 한 쌍이 나른하게 기대어 앉아 있다. 푸른 녹음에 적신 음이온 공기를 들이마시며, 살결로 연인의 체온을 느끼고, 시간이 멈춘 듯한 여유로운 오후를 만끽하고 있다.

이 연인, 토가시 유타와 타카나시 릿카는 지금 아무 말이나 나누며 수다를 떨고 있다.

2.가상 뼈란 무엇인가

유타: 이번 숙제는 선생님이 가상 뼈를 쓰라고 하셨어. 하아, 머리 아프다. 나도 가상 뼈는 아직 반쯤만 이해했거든. 릿카, 너는 가상 뼈 이해했어?

릿카: 아니…… 그, 아니면 회향 언니한테 물어볼까?

유타: 오! 좋은 생각이다 릿카. 회향 언니는 작년에 이미 이런 걸 배웠을 테니까 분명 알 거야. 내가 전화해 볼게.

그렇게 말하며 유타는 소파에서 일어나 식탁 앞으로 가 회향 언니에게 영상 통화를 걸었다.

릿카: 유타가 나 몰래 다른 여자 번호를 저장해 두고……

유타: 바보야…… 여보세요, 회향 언니 맞죠? 아, 그게…… 질문이 좀 있어서요. 저랑 릿카 둘 다 가상 뼈 챕터를 잘 못 알아들어서, 선생님께 직접 여쭤보기는 좀 그래서요. 시간 되시면 설명해 주실 수 있을까요?

회향: 오? 너희 둘, 귀한 휴일인데 서로 들러붙어 있지 않고 공부까지 한다고?

유타: 언니, 놀리지 마세요 = =

회향: 하하하, 정말 순수하네, 토가시 군~ 음…… 가상 뼈지? 어디 보자……

회향: 찾았다! 이게 작년에 내가 정리한 수업 노트야. UE4 UE5 스켈레탈 애니메이션 고급 로코모션 시스템 발 IK - 즈후 (zhihu.com) 여기 가상 뼈 소절을 봐. 작년에 좀 대충 적어 둬서 설명이 명확하지 않을 수도 있어. 대충 보면서, 이따 내 설명이랑 맞춰 보면 돼.

유타: 네, 감사합니다 언니.

그렇게 말하며 유타는 라인으로 회향이 보낸 노트 사진을 내려받았다. 겸사겸사 전화를 스피커폰으로 바꿨다.

회향: 그리고 이게 너희 올해 새로 쓰는 교재일 거야. 언리얼 엔진의 가상 뼈 | 언리얼 엔진 5.0 문서 (unrealengine.com). 하아, 부럽다. 우리 작년엔 교재도 없었는데……

릿카: 근데 이 교재는 도무지 이해가 안 돼요. 가상 뼈 정의가 뭔지도 제대로 안 알려 주잖아요…… 흑흑……


【위 이미지 설명 · 한국어 번역】

가상 뼈 개요 (Virtual Bone Overview)

가상 뼈는 다른 뼈의 변환(Transform)을 따르지만 서로 다른 본 스페이스(Bone Space)에 위치하는 뼈입니다. 대부분의 경우, 이는 가상 뼈가 루트 본(Root Bone)의 자식 노드가 되지만 손이나 발 같은 말단 본(End Bone)의 뒤를 따르게 됨을 의미합니다.

다시 말해, 가상 뼈는 해당 목표 본을 향하는 모든 관절의 전방 운동학(FK) 계층 구조에 따른 추가적인 영향을 받지 않고, 목표 본을 직접 따라갈 수 있습니다. 이 기능을 사용해 역운동학(IK) 시스템을 설정하고 캐릭터의 손발이 가상 뼈를 따르도록 만들면, 복잡한 애니메이션 시스템에서 발생하는 '슬라이딩 현상(Foot Sliding/Swimming)' 및 기타 손발 떨림 문제를 해결할 수 있습니다.

회향: 아하하, 확실히 좀 그렇지. 그럼 나…… 내 이해대로 한번 말해 볼까?

너희는 스켈레톤이랑 스키닝 기술은 배웠지? 각 스키닝 부위가 어떤 뼈에 얼마만큼 가중치를 받는지 그런 거……

릿카: 배웠어요.

회향: 좋아. 그럼 먼저 첫 번째, 꼭 기억해. 가상 뼈는 뼈이지만, 어떤 스키닝도 제어하지 않아.

유타: 그게 바로 “가상”이라는 말의 의미인 건가요?

회향: 내 생각엔 그런 것 같아. 보통 새 뼈 하나가 어떤 스키닝을 제어하게 하려면 블렌더 같은 툴에서 버텍스 그룹 데이터를 손봐야 하거든. 그런데 언리얼 엔진에서 가상 뼈를 하나 추가할 때는 그냥 추가하면 끝이야. 버텍스 그룹을 만지며 스키닝을 연결하는 단계가 없지.

“가상”의 뜻은 이제 알겠고, 다음은 “뼈”야. 뼈로서의 성질도 가지고 있어. 예를 들어 부모 뼈가 움직이면 같이 움직이고, 자기 자신은 컴포넌트 스페이스는 물론 월드 씬 스페이스에서의 변환도 부모 뼈의 영향을 받아.

릿카: 응응.

회향: 이제 가상 뼈가 가진 성질을 몇 가지 말해 줄게.

첫 번째 성질은, 애니메이션 리타겟팅 시 가상 뼈의 Local 변환은 원본 애니메이션에서 가져온다는 점이야——즉 이동, 회전, 스케일(보통 애니메이션에서 스케일을 건드릴 일은 거의 없지만)이 전부 원본 애니메이션과 일치한다는 뜻이지. 뭐, 애초에 이동 리타겟팅 옵션 자체가 없으니까. 이동 리타겟팅 옵션을 “애니메이션”으로 둬야만 자신의 변환이 원본 애니메이션과 같아지는 IK 스켈레톤 트리랑은 길을 달리하면서도 비슷한 지점에 도착하는 셈이지.

릿카: 유타, 이동 리타겟팅 옵션이 뭐야?

유타: 하아, 수업 때 또 잔 거지? 선생님이 분명히 설명해 주셨잖아……

릿카: 회향 언니…… 유타가 나 괴롭혀요……

회향: 하하, 너희 티격태격하는 거 보기 좋다. 괜찮아. 릿카가 잊었으면 내 노트 1.1절을 펴 봐. 거기 적혀 있어~


【위 이미지 설명 · 한국어 번역】

1.1 애니메이션 리타겟팅과 IK — 이동 리타겟팅 모드

일반적으로 루트 본, IK 본, 무기 본은 애니메이션(Animation) 모드를 사용한다. 골반은 스케일 애니메이션(Animation Scaled) 모드를 사용해 올바른 높이에 위치하도록 한다. 그 외 나머지 뼈들은 전부 스켈레톤(Skeleton) 모드를 사용한다. 여기서는 가장 자주 쓰이는 이 세 가지 스켈레톤 이동 리타겟팅 모드를 소개한다.

애니메이션 모드: 이 뼈는 새 모델이 어떻게 생겼든 무시하고, 애니메이션 속 원본 뼈의 이동값을 충실하게 그대로 따른다. IK 뼈들을 전부 애니메이션 모드로 설정한다는 것은, 리타겟팅 시 추가적인 관절 이동이 발생하지 않고 원래의 움직임을 그대로 유지한다는 뜻이다. 이 변하지 않는 성질을 이용해서, 손과 발을 항상 원래의 위치에 고정시킬 수 있다. 이 특성은 관절을 고정된 위치에 락(lock)해야 하는 요구를 아주 잘 만족시켜 주며, 씬과의 상호작용에서 자주 쓰인다. 스케일 애니메이션 모드: 애니메이션 속 원본 뼈의 이동값을 사용해 자신의 이동값을 설정하되, 원본 모델과 새 모델의 비율에 맞춰 이 이동값을 스케일링한다. 골반이 스케일 애니메이션 모드를 사용하면 캐릭터가 움직일 때 땅 위에 올바르게 서 있을 수 있다. 만약 애니메이션 모드를 사용한다면 땅딸막한 캐릭터의 골반은 위로 끌려 올라가고, 키 큰 캐릭터의 골반은 아래로 끌려 내려가게 된다. 스켈레톤 모드: 애니메이션의 뼈 이동값을 무시하고, 곧바로 해당 모델(즉 새 모델)의 뼈 이동값을 그대로 사용한다. 대부분의 나머지 뼈들이 이 옵션을 사용한다. 주의할 점은, 만약 원본 애니메이션이 루피의 “고무 주먹” 혹은 “통비권”처럼 손목 관절을 앞으로 크게 이동시킨 동작이라면, 손목 관절을 여전히 스켈레톤 모드로 두었을 때 리타겟팅된 새 애니메이션에서는 손목 관절이 애니메이션의 이동값을 따라가지 않아서, 원하는 결과를 얻지 못하게 된다는 것이다.

릿카: 에헤헤, 회향 언니가 나한테 진짜 잘해 줘요~

회향: 방금 가상 뼈랑 애니메이션 이동 옵션을 쓴 IK 스켈레톤 트리가 “다른 길로 같은 곳에 도착한다”고 말했지만, 사실 그 표현이 아주 정확하진 않아. 왜냐하면 IK 스켈레톤 트리는 애니메이션의 원본 정보를 보존하려고 트리 전체가 애니메이션 이동 옵션을 쓰기 때문이야. 그리고 IK 스켈레톤 트리의 부모 뼈는 root뿐이라서, IK 스켈레톤 트리는 원본 애니메이션 데이터를 완전히 그대로 쓰고, 모델 변화——즉 부모 뼈 이동 변화가 주는 영향은 전혀 받지 않아.

유타: 가상 뼈는 그렇지 않나요?

회향: 좋은 질문이야~ 가상 뼈와 애니메이션 이동 옵션을 쓴 IK 스켈레톤 트리, 둘의 공통점은 자신의 Local 변환이 원본 애니메이션에서 온다는 점이고, 다른 점은 가상 뼈가 시작 뼈 아래에 걸려 있다는 거야. Local 변환 자체는 안 변하지만, 부모 뼈가 바뀌면 리타겟팅 후에 자기 자신의 컴포넌트 스페이스 좌표계 변환이 바뀌게 되지~

유타: 오오, 거기에 그런 미세한 차이가 있었군요.

릿카: 가상 뼈가 시작 뼈 아래에 “걸려” 있다고요? 야야, 회향 언니, 설명해 주세요~

회향: 아, 두 번째 성질 내용을 살짝 끌어와 버렸네. 마침 첫 번째 성질도 끝났으니, 릿카 궁금증을 따라가며 이어서 말할게.

두 번째 성질은, 가상 뼈가 단순한 뼈 하나가 아니라 방향성을 가진, 시작 뼈에서 목표 뼈를 가리키는 뼈라는 점이야. 물론 누가 누구를 가리킬지는 에디터에서 새 가상 뼈를 만들 때 지정할 수 있지.

릿카: 그럼 언니가 말한 “걸린다”는 건, 가상 뼈가 시작 뼈를 자신의 부모 뼈로 삼는다는 뜻인가요?

회향: 정답~

유타: 그럼 가상 뼈를 만들고 나면 위치는 어디인가요? 부모 뼈 위치랑 바로 겹치나요?

회향: nonono~ 그게 바로 가상 뼈의 세 번째 성질이야.

세 번째 성질은, 가상 뼈의 Local 변환은 생성 시점에 직접 지정할 수 없고, 시작 뼈와 목표 뼈의 컴포넌트 스페이스 변환 차이값을 실시간으로 계산해서 얻는다는 점이야.

릿카: 그 변환 차이값은 어떻게 계산해요? 그냥 둘을 빼면 되나요?

회향: 음… 그렇게 단순하진 않아. 구체적으로 어떻게 계산하는지는 내 노트 1.2절 소스 코드에 공식이 붙어 있어.

다만 너희가 거기까지 깊게 알 필요는 없다고 생각해. 그냥 이렇게만 기억하면 돼. “가상 뼈의 Local 이동량은, 시작 뼈에서 출발해 컴포넌트 스페이스에서 목표 뼈에 도달하고 목표 뼈 위치와 겹치게 만드는 이동량으로 설정된다.”

봐, 내가 만든 이 골반에서 머리를 가리키는 가상 뼈도, 시작 뼈인 골반에서 출발해 위로 올라가 목표 뼈인 머리까지 닿잖아~

유타: 회전이랑 스케일은요?

회향: 그것도 같아. 내가 이동으로 설명한 건 상상이 제일 쉽고 직관적이니까 그런 거야.

화면 너머의 회향은 유타가 고개를 숙이고 생각에 잠긴 듯한 표정을 짓는 걸 보았다. 방금 한 말을 소화하고 있는 모양이었다.

회향: 너무 많이 말했더니 좀 피곤하다~ 릿카, 방금 내가 말한 내용 정리해 볼래?

회향은 그렇게 말하며 포근한 양 베개 위에 엎드렸다.

릿카: 음… 생각해 볼게요……

가상 뼈…… 가상 뼈는 스키닝을 제어하지 않는 뼈예요. 방향성이 있어서 시작 뼈에서 목표 뼈를 가리키고요. 만들면 시작 뼈의 자식 뼈가 되고, 자신의 변환값 덕분에 컴포넌트 스페이스에서 목표 뼈와 딱 겹쳐요. 이동 리타겟팅 옵션이 없어서, 리타겟팅 후에도 원본 애니메이션에 있던 자신의 Local 변환값을 유지해요.

회향: 맞아 맞아~ 릿카 제대로 들었네~

릿카: 흠흠! 당연하지! 이 정도쯤이야 사왕진안의 힘으로는 식은 죽 먹기지!

회향: 그럼 하나만 더 보충할게. 방금 『이동 리타겟팅 옵션이 없어서 리타겟팅 후에도 원본 애니메이션의 Local 변환값을 유지한다』고 했잖아. 그게 뭘 의미하는지 알아?

유타: 의미라고요?

회향: 음…… 생각해 보자. 릿카, 지금 일어나서 양손을 앞으로 수평으로 들어 봐!

릿카: 어…… 어어!

릿카는 자리에서 일어나 양손을 앞으로 수평으로 들었다.

회향: 작은 상상을 해 보자. 지금 릿카 몸에 왼손에서 오른손을 가리키는 가상 뼈가 하나 있다고 치자. 이 가상 뼈를 왼손에 든 작은 나무 막대라고 상상해 봐. 처음에는 가상 뼈의 성질 때문에, 이 막대 끝부분이 반드시 오른손에 딱 쥐어져 있어야 해. 맞지?

릿카는 그 말에 책상 위 긴 젓가락을 집어 왼손으로 젓가락 머리를 잡고, 양손을 앞으로 수평으로 든 채로 오른손이 젓가락 끝을 딱 쥐도록 했다.

릿카: 응응! 맞아요!

회향: 이제 너를 스켈레톤 리타겟팅해서, 키 1미터 90인 체육 선생님 몸으로 바꿔 보자. 그럼 이 작은 나무 막대에는 무슨 일이 생길까?

릿카: 생각해 볼게요. 막대 길이는 그대로일 거예요. 가상 뼈의 변환은 리타겟팅 전후에 안 변하니까요. 그런데 어깨가 넓어진 스켈레톤이 됐으니, 막대는 여전히 왼손에 쥐어져 있어도 끝부분은 오른손에 닿지 않게 돼요.

회향: 잘했어~ 그럼 내가 지금 이중 본 IK로 네 오른손을 그 막대 끝으로 다시 맞춰 주면, 또 막대를 딱 쥘 수 있게 되겠지?

릿카: 네!

회향: 이 예를 이어서 생각해 봐. 만약 예전처럼 IK 스켈레톤 트리로 양손이 막대를 쥐고 있을 때의 위치를 표현했다면, 리타겟팅 후에도 네 어깨는 이미 1미터 90인데 IK 스켈레톤 트리는 여전히 1미터 50 자리에 남아 있겠지. 그때 양손을 이중 본 IK로 막대 머리와 끝에 맞추면 어떻게 될까?

릿카: 양손이 더 이상 앞으로 수평으로 든 상태가 아니라, 배꼽 높이까지 내려가서 막대를 쥐게 돼요.

회향: 센스 좋네, 릿카~ 가상 뼈가 컴포넌트 스페이스에서 모델과 함께 위치가 바뀌는 특성은, 캐릭터가 자기 몸에 붙은 물건을 제대로 쥐게 하는 데 쓸 수 있어——즉 캐릭터와 같이 움직이고, 모델 크기가 바뀌면 위치도 같이 바뀌는 것들. 반면 IK 스켈레톤 트리는 위치가 절대 안 바뀌니까, 캐릭터가 월드 씬과 상호작용할 때 어울려——씬 안에 고정돼 있고 캐릭터가 움직여도 위치가 안 바뀌는 것들.

릿카: 에헤헤…… 잠깐, 언니 방금 나 키 1미터 50이라고 한 거예요?!

회향: 괜찮다 괜찮다~ 몸집이 아담한 릿카가 더 귀엽지. 보호해 주고 싶게 만들거든. 그렇지, 토가시 군?

유타: 맞는 말이긴 해요. 아담한 릿카는 확실히 귀엽죠. 그래도 릿카가 어떤 모습이 되든, 나는 변함없이 좋……

릿카: 아아아아! 휴… 휴대폰! 배터리 다 됐어! 고마워요 회향 언니! 나나나 먼저 끊을게요!

전화가 끊기기 직전, 수줍음에 얼굴이 새빨개져 허둥대는 릿카를 보며 회향은 흐뭇한 미소를 지었다.

“젊음이 좋긴 하지~”

3.가상 뼈로 무기 쥐기 구현하기

며칠 뒤 어느 점심, 은행학원에 하교 종이 울릴 무렵 유타는 도시락을 들고 릿카 맞은편에 앉았다.

유타: 릿카, 큰일이야. 이번 조별 숙제에 문제가 생겼어. 우리 조 아티스트가…… 자기만의 생각이 좀 강하거든.

릿카: 왜, 유타?

유타: 이번 조별 숙제가 데저트 이글 두 자루를 손에 바인딩하는 거잖아? 게다가 다른 스켈레톤으로 리타겟팅해도 제대로 쥐고 있어야 하고.

릿카: 내 종복 DarkFlameMaster로서, 그 정도에 겁먹을 건 아니지?

유타: 바보야. 정말 그렇게 단순하면 좋겠는데. 우리 조 아티스트가 고집 세서, 데저트 이글 두 자루를 에셋 하나에 억지로 넣었거든. 그래서 총 사이 간격이 고정돼 버렸어. 원래는 총 한 자루를 한 손에 꽂으면 됐는데, 이제는 그 간격에 맞춰 손이 총을 “꽂으러” 가야 해.

릿카: 그럼 어떻게 해? 선생님은 팀워크를 기르라면서 조원 교체도 안 된대…… 유타, 빨리 방법 생각해 봐!

유타: 하아, 일단 아이디어는 하나 있어. 지금 대략적인 흐름을 말해 줄게.

이 무기의 루트 본(root)은 가운데 검은 점이고, 두 총 모델은 루트 본에서 각각 고정된 거리만큼 떨어져 있어. 기억하기 쉽게 데저트 이글 루트 본에서 왼쪽 총까지의 거리를 L이라고 할게.

이 무기를 캐릭터에 붙이려면, 무기를 캐릭터의 ik_hand_gun 뼈에 Attach하면 돼. 그러면 무기 root가 ik_hand_gun과 겹치지.

릿카: 응응.

유타: 하아, 아티스트는 총 모델만 만들고 더 안 하겠다고 해서, 애니메이션은 내가 해야 했어.

총 쥐는 애니메이션을 만들 때는 먼저 ik_hand_gun을 가슴 앞으로 당긴 다음, 양손을 각각 ik_hand_gun 옆 일정 거리에 놓아서 양손이 총을 딱 쥐도록 해야 해. 루트에서 왼쪽 총까지 거리가 L이니까, 왼손이 왼쪽 총을 딱 쥐려면 왼손 hand_l에서 ik_hand_gun까지의 거리도 정확히 L이어야 하거든. 오른손도 마찬가지.

릿카: 여기까지면 첫 번째 숙제는 성공이네. 데저트 이글을 손에 꽂았어.

꽤 순조롭잖아, 유타.

유타: 두 번째 숙제, 리타겟팅이 진짜 골치야 = = 선생님이 준 목표 스켈레톤이 꽤 건장한 체형이라 어깨가 넓어. 원래라면 두 총 사이 간격을 더 벌려야 하는데, 우리가 받은 모델은 간격이 아티스트에 의해 묶여 버려서…… 총 거리를 못 바꾸니, 양손이 다시 총 위치로 쥐도록 만드는 수밖에 없었어.

릿카: 손을 다시 총 위치에 맞추려면, 두 총이 컴포넌트 스페이스에서 각각 어디에 있는지를 알아야 해. 그런데 지금은 총의 루트만 ik_hand_gun에 있다는 것만 알고, 두 총의 구체 위치는 모르는 거 아니야? 프로그래머인 우리가 에셋 안에서 두 총이 root에서 얼마나 떨어져 있는지를 직접 찾아서 그 오프셋까지 더해야 해?

유타: 그건 안 해도 될 것 같아. 방금 내가 만든 애니메이션 안에 이미 그 오프셋이 들어 있거든. 루트에서 왼쪽 총까지의 거리랑, 왼손에서 ik_hand_gun까지의 거리가 같아. 둘 다 L이야.

릿카: 오오~! 역시 유타!

유타: 여기서 가상 뼈로 두 뼈 사이 거리를 기록하면 돼. 먼저 가상 뼈 두 개를 만들어 데저트 이글 모델의 루트 본(root)에서 양손까지의 거리를 적어 둘게. 그중 VB LHS_ik_hand_gun의 길이는 hand_l에서 ik_hand_gun까지의 거리, 즉 L이야.

유타: 좋아…… 리타겟팅 중…… 끝.

릿카: 이제 어깨가 넓어져서 양손 사이 거리도 멀어졌네. 원본 애니메이션에서는 겹쳐 있던 가상 뼈 두 개도 지금은 꽤 떨어져 있어.

유타: 맞아. 다음 첫 단계는 이 무기를 VB_LHS_ik_hand_gun 소켓에 Attach하는 거야.

가상 뼈 VB_LHS_ik_hand_gun 길이가 L이니까, hand_l에서 VB_LHS_ik_hand_gun까지의 이동은 +L이야. 그 위치에 데저트 이글 루트 본을 내려놓으면, 루트에서 왼쪽 총까지는 다시 -L 이동을 거치게 돼. 더하고 빼면, 왼쪽 총이 왼손 위에 딱 올라가게 되지.

유타: 다음은 오른손이야. 오른손이 오른쪽 총을 다시 제대로 쥐게 하려면, 오른손에서 총 루트까지의 거리를 알아야 해. 음…… 그 거리는 가상 뼈 VB RHS_ik_hand_gun에 들어 있지. 생각해 보자…… 릿카, 이때는 어떻게 하면 좋을 것 같아?

릿카: 아래 그림 같은 결과를 내려면, VB RHS_ik_hand_gun을 이중 본 IK로 VB LHS_ik_hand_gun 위치에 맞추면 되지 않을까? 그러면 부모 뼈인 hand_r도 같이 끌려오겠지?

유타: 그 생각 괜찮은데, 작은 문제가 있어. 그렇게 하면 hand_r은 중간 관절이라서, 이중 본 IK에서 놓을 수 있는 위치가 무한히 많지 않아? hand_l과 같은 높이에 두고 총을 딱 쥐게 하려면, 관절 목표 위치를 아주 정밀하게 맞춰서 말단 뼈 위치, 루트 뼈 위치, 관절 목표 위치 세 점이 만드는 평면이 총을 올려둔 그 평면과 정확히 일치하게 해야 해. 그래야 hand_r 해가 총이 놓인 평면 위에 떨어져.

릿카: 흥, 그 정도는 쉽지. hand_r과 VB RHS_ik_hand_gun 사이에 가상 뼈를 하나 더 만들어서, 이중 본 IK에서 hand_r을 중간 관절에서 루트 관절로 올리면, 위치 해를 구하는 번거로움을 피할 수 있잖아?

유타: 칭찬받으니까 바로 기고만장해지네…… hand_r을 이중 본 IK의 루트 관절로 올리면, 루트 관절은 끌려가지 않아. 그러면 이렇게 돼……

릿카: 으음……! 사왕진안이 실수하다니……

유타: 올바른 방법은 가상 뼈를 한 층 더 만드는 거야. 앞에서 만든 VB LHS_ik_hand_gun과 VB RHS_ik_hand_gun은 둘 다 데저트 이글 루트가 놓일 위치를 가리키기 위한 것이었어. 지금 만들 가상 뼈는 손이 놓일 위치를 가리키기 위한 것이야.

유타: 봐, 이게 리타겟팅 전 원본 애니메이션에 두 번째 층 가상 뼈를 더한 모습이야.

유타: 그리고 리타겟팅 후 지금은 이렇게 보여.

유타: 이제 어떻게 하면 될지 알겠어?

릿카: 당… 당연하지! 그냥…… 그냥 hand_r을 이중 본 IK로 VB LHS_ik_hand_r 위치에 맞추면 되, 되는 거지……?

유타: 맞아. 방금도 말했지만, 이 가상 뼈 세트는 손이 놓여야 할 위치를 가리키는 거니까.

릿카: 에헤헤, 유타, 나 칭찬해!

유타: (무시)후…… 이걸로 겨우 선생님 요구를 맞췄다.

릿카: 원래는 유타가 나한테 도움 받으러 온 건데, 왜 결국 네가 나한테 가르쳐 주는 쪽이 된 거지…… 왜 이렇게 됐을까……

유타: 릿카 옆에 있으면, “내가 모르면 이 바보는 누가 가르쳐 주지?” 하는 느낌이 들거든.

릿카: 으으……! 분하다, 얕보이다니……

릿카는 머리를 감싸 쥐고, 유타 방안에서 흠집을 찾아내려 했다.

릿카: 맞다 유타, 너 마지막에 가상 뼈 두 개를 안 썼잖아…… VB RHS_ik_hand_gun이랑 VB RHS_ik_hand_l은 안 쓰고, hand_r이 이중 본 IK로 끌려갈 때 따라간 것뿐이네.

유타: 괜찮아, 그게 정상이야. 반대로 오른손은 그대로 두고 왼손이랑 두 총을 전부 오른손 쪽으로 끌어오려면, 네가 말한 그 두 가상 뼈가 쓰이고 나머지 둘은 할 일이 없어지지.

릿카: 으음… 계획 실패……

유타: 점심시간 끝나기 전에 시간이 좀 남았으니까, 릿카 너한테 문제 하나 내 볼게. 이번 경험이 나중에 어떤 상황에서도 쓸 수 있을 것 같아?

릿카: 음…… 무기 자체가 양손이 필요하고, 정적 메시 전체의 컴포넌트 스페이스 위치만 알고, 양손이 정확히 어디를 쥐어야 하는지는 모르는 경우겠지.

유타: 맞아. 예를 들어 소총을 멜 때도 마찬가지야. 애니메이터가 소총을 멘 애니메이션을 줬을 때, 우리는 그 총의 root가 캐릭터 ik_gun_root와 겹친다는 것만 알고, 왼손과 오른손이 어느 뼈를 쥐어야 하는지는 전혀 몰라——캐릭터 스켈레톤 안에도 그 위치를 알려 주는 뼈 두 개가 애초에 없으니까.

릿카: ik_hand_l이랑 ik_hand_r 아니야?

유타: 당연히 아니지. 그 두 뼈는 위치가 고정된 씬 소품과 상호작용할 때만 어울려. 리타겟팅 때 그 뼈들은 원본 애니메이션의 ik_hand_l, ik_hand_r 이동값을 그대로 쓰거든. 새 목표 모델이 아주 키가 크면, 그 뼈들이 가리키는 총 멘 위치가 무릎 쪽으로 내려가 버리지 않겠어?

릿카: 그렇구나…… 그래서 리타겟팅 후에 총을 ik_hand_gun에 Attach하지 않는 거구나. 그때의 ik_hand_gun은 원본 모델 가슴 위치를 가리킬 뿐, 지금 모델의 가슴 위치를 대표하진 않으니까.

유타: 이해 잘했어. 그러니까 앞으로 이런 상황을 만나면, 순서는 항상 같아. 먼저 무기를 VB LHS_ik_hand_gun에 Attach해서 무기와 첫 번째 손(왼손) 사이 간격을 맞추고, 그다음 두 번째 손(오른손, hand_r)을 이중 본 IK로 VB LHS_ik_hand_r 위치에 맞춰서 무기와 오른손 사이 간격도 맞추는 거지.

릿카: 오오~~ 좌우를 바꿔도 마찬가지지? 무기를 VB RHS_ik_hand_gun에 Attach하고, hand_l을 이중 본 IK로 VB RHS_ik_hand_l 위치에 맞추면 되지?

유타: 응, 이제야 좀 트였네.

릿카: 유! 타! 역시 나를 계속 바보 취급한 거지?

유타: 참고로 ALS에서는 hand_l 이중 본 IK를 앞에 두는데, 그러면 왼손이 늘 오른손 쪽으로 끌려가게 돼.

릿카: 흥~! 그건 나도 알아. 무기를 왼손에 붙여도, 리타겟팅 후 오른손은 오른쪽 위 구석에 그대로 있고, 이중 본 IK를 실행해야 VB LHS_ik_hand_r 위치로 끌려오거든. 그림에서는 매번 왼손 이중 본 IK를 먼저 하니까, 그때 hand_r이랑 VB RHS_ik_hand_l은 아직 오른쪽 위에 있지. 왼손이 당연히 그쪽으로 끌려가지~

유타: 응응, 잘했어 잘했어.

점심시간이 거의 끝나가니까, 빨리 도시락 먹자.

릿카: 잠깐! 유타, 내가 먹여 줄게! 자, 아——

유타: 알, 알겠어…… 아——

수줍음과 설렘을 안고, 릿카의 하얀 손목이 입가로 가져온 음식을 한입 베어 물었다——

“릿카! 또 네가 안 먹는 토마토를 나한테 먹인 거지!”

3.5 약간의 수업 외 확장

가상 뼈는 원본 애니메이션의 애니메이션 데이터에만 충실하고, 우리가 뼈를 수정하거나 리타겟팅하는 행위 따위에는 신경 쓰지 않는다. Modify Bone이든 Two Bone IK든 후처리를 해도 가상 뼈의 길이는 영향을 받지 않는다.

아래 그림처럼, 발 IK 때문에 캐릭터 골반이 크게 아래로 끌려 내려갔는데 IK 트리는 골반을 따라 같이 내려가지 않았다(청록색 구가 ik_hand_gun 위치). 그래서 hand_l에서 ik_hand_gun까지의 거리가 바뀌었다(50에서 46으로 짧아짐).

만약 가상 뼈가 현재 포즈의 뼈 변환 차이값을 실시간으로 계산한다면 같은 값이 나와야 하지만, 실제로는 그렇지 않다. 가상 뼈 길이는 그대로다. 그림에서 노란색 구는 hand_l 위치, 빨간색 구는 가상 뼈 VB LHS_ik_hand_gun 위치인데, 여전히 왼손에서 출발해 같은 거리를 지나 오른손이 원래 무기를 쥐고 있어야 할 자리까지 도달한다.

후기

최근에 예전에 쓴 글들을 다시 읽어 보니, 어느새 나도 모르게 고정된 문체가 잡혀 있었다——그리고 그 문체가 썩 마음에 들지도 않았다. 그래서 새로운 문체를 한번 시도해 보고 싶었다——어떻게 하면 글이 엄밀하면서도 최대한 재미있고, 독자가 부담 없이 읽을 수 있을까.(또 다른 이유는, 면접 준비를 위해 1년 전 글을 복습하다 소스 코드가 줄줄이 붙고 그림은 적고 글자만 많은 본문을 보니 정말 머리가 핑핑 돌아서, 타임슬립해서 1년 전 나에게 뺨을 두 대 갈기고 싶을 정도였다. 그래서 글을 더 읽기 쉽게 쓰겠다고 마음을 먹었다.)

몇 해 전 읽었던 청제 선생님의 《대화로 배우는 자료구조》와 《대화로 배우는 디자인 패턴》이 떠올랐다. 그 두 교재는 전문성을 잃지 않으면서도 충분히 재미있어서 끝까지 읽게 만들어 주었다. 그중 《대화로 배우는 디자인 패턴》은 대화 형식으로 수업을 전개했고, 블로그에서 발전한 책이었다. 그래서 그 스타일을 한번 흉내 내 보기로 했다.

이 글은 형식과 문체를 바꾸다 보니, 평소 글보다 시간과 정력이 훨씬 더 들었다. 게다가 마음이 많이 조마조마했다. 누군가는 좋아해 줄까, 누군가는 오히려 이런 형식이 더 읽기 어렵다고 느낄까, 아니면…… 아무튼 독자 여러분께서 공로까지는 아니더라도 고생은 봐 주시길, 좋아요를 많이 눌러 주셔서 내가 글을 “더 재미있고, 더 읽기 쉽게” 만들려고 들인 노력을 응원해 주셨으면 한다. 동시에 어떤 피드백이든, 긍정적이든 부정적이든, 구체적일수록 좋다. 그래야 글쓰기 방식과 스타일을 어떻게 다듬을지, 지금 이 시도가 맞는 방향인지 알 수 있으니까.

또 어떤 독자는 이렇게 말할지도 모른다. “어, 발 IK 편에서 이미 가상 뼈를 썼는데 이번에도 또 쓰면, 같은 내용으로 두 번 우려먹는 거 아니야?

나도 그 점을 고민했다. 이번에 가상 뼈를 다시 쓴 이유는, 지난번 글이 나 자신조차 만족시키기 어려웠고, 독자를 만족시키기는 더더욱 어려웠기 때문이다. 지금 다시 보면 틀린 내용은 거의 없지만(내 기준으로는), 당시 가상 뼈에 대한 이해가 여전히 흐릿한 부분이 많았다. 웅얼웅얼 떠들고 나서도 무슨 말인지 모를 정도였으니, 그런 글을 독자가 이해해 주길 바라는 건 너무한 일이었다.

(나중에

@Zero

선배께 특별히 여쭤 보고 친절한 가르침을 받았다. 진심으로 감사드린다.)


【위 이미지 대화 내용 · 한국어 번역】

(09-03 14:48)

DarkFlameMaster: Hand IK 기준으로 보면, 예를 들어 ALS_Props_Pistol_2H_Poses 같은 애니메이션에서 무기는 오른손에 붙어 있고, 왼손 IK만 들어가요.

(09-03 14:53)

DarkFlameMaster: 그리고 그 애니메이션의 VB RHS_ik_hand_l이 기록하는 건 무기 마운트 포인트 → 왼손 위치예요(순서 주의). 실제로는 쥐고 있는 상태에서 왼손이 무기(오른손)에 대해 상대적으로 어디에 있는지를 뜻하죠. 게다가 이 가상 뼈는 오른손 hand_r에 걸려 있어요. 그래서 왼손만 IK로 끌어가면, idle pose 안에서 왼손과 무기(오른손)의 상대 위치를 유지할 수 있어요. 즉 무기를 쥐는 상태가 되는 거죠. 여기서 전제 조건은 무기 마운트 포인트와 오른손 사이에, 그 위치를 바꿔 버릴 다른 중첩 처리가 없어야 한다는 점이에요.

독자들도 느끼겠지만, 이번 가상 뼈 설명은 훨씬 더 체계적이다. 게다가 이전 발 IK 편처럼 설명만 하고 써먹을 곳이 없었던 것과 달리, 이번에는 가상 뼈를 설명한 직후 ALS의 무기 쥐기에 바로 적용했다. 독자가 익히고 이해하는 데 도움이 될 거라고 믿는다.

그럼 왜 발 IK 편의 가상 뼈 부분을 직접 다시 쓰지 않았느냐면, 그 글이 너무 길어서다 = = 글 길이 상한까지 글자가 얼마 안 남았었다…… 그리고 배운 뒤 바로 써먹는 문제까지 고려해서 이번 글로 옮겼다. 이 선택이 옳았다는 걸 결과가 증명해 주길 바란다.

마지막으로, 필자 수준이 부족해 글에 틀린 곳이나 빠진 곳이 있을 수밖에 없다. 독자 고수 여러분의 따끔한 지적과 가르침을 부탁드린다.

PS: 겸사겸사 여기서 필자가 막 개설한 UE 스켈레탈 애니메이션 교류방도 살짝 홍보해 본다: 916274600, 여러 고수님들의 방문과 가르침을 환영한다.

다음 글: 기대해 주세요

에밀리아: 왜… 나를 도와준 거죠?