컨트롤 릭이란?
언리얼 엔진 내에서 캐릭터를 직접 리깅 및 애니메이팅할 수 있는 애니메이션 툴 세트이자 솔루션. 컨트롤 릭을 사용하면 리깅 및 애니메이팅 작업에 외부 툴을 이용할 필요가 없고, 직접 애니메이팅할 수 있음.
간단하게 자동차에 탑승하는 애니메이션을 재생시킬 때 문의 손잡이와 운전대에 손을 정확히 얹도록 하는 강좌.
- 우선 자동차의 스켈레탈 메쉬에 동적으로 움직여야할 문과 운전대에 본이 추가되어야 한다(리깅).
- 그리고 리깅된 자동차 스켈레탈 메쉬에 IK용 소켓을 추가해줘야 함.
- 캐릭터 AnimBP에서 Montage Slot과 Output Pose 노드 사이에 Two Bone IK 노드를 두 개 연달아 배치함. IK 노드에서 설정을 해줘야 함(어떤 본을 IK로 타게팅할건지, 이펙터의 로케이션 공간은 뭔지(월드공간), Joint Target 설정). 각 IK 노드의 Alpha와 Effector Location 파라미터를 변수로 빼고, Event Graph에서 제어해주면서 IK가 되도록 해줌.
- 애니메이션 시퀀스 또는 몽타주에서 Curves를 사용함. Curves는 대충 내가 원하는 경우에 대한 0과 1사이 값을 시간에 따라 제어할 수 있는 기능임. 이 강의에서 CarDriverDoorLeftHand 커브를 예시로 들면 애니메이션 타임라인에서 문 손잡이를 잡는 구간동안 커브를 1로 올리고 잡고있지 않을 때를 0으로 설정해주고, 이 커브 값을 IK 노드의 Alpha 파라미터로 넣어주는 용도인 것.
- 어쨌든 커브가 1로 증가하기 시작할 때 notify를 추가해 IKTarget 로케이션을 설정할 수 있게 타이밍을 잡아줌. 노티파이 이벤트를 받으면 별도로 만들어둔 Enum 변수(문 바깥/안쪽 손잡이, 스티어링휠 3개 분기)를 Set해주고, Enum 변수가 AnimBP Update 이벤트에 따라 변경 후 로직을 실행할 때 아래 로직을 실행함
- Vehicle 액터를 찾아서 위 Enum에 따라 소켓의 월드 좌표를 Set하고 IKTarget 로케이션 변수에 업데이트함. 그리고 Get Curve Value 노드로 몽타주에서 추가했던 Curve의 이름을 걸어주어 그 값을 IKAlpha에 업데이트함.
IK와 가상 본
An Inverse Kinematics (IK) setup uses a start and end position, to orient your joint chain. “Inverse” because you define the end position you want to reach and the solver calculates the angles to get there.
Opposed to Forward Kinematics (FK), which lets you define the joint angles directly. In that case the final joint simply goes along for the ride and ends up wherever it was carried to.

(출처:Rig Fundamentals: PoleVector - Mischa Kolbe)
IK는 시작점과 끝점만 정해두고 그 중간 조인트 체인은 '솔버'가 계산해 설정해주는 방식. FK는 반대로 조인트 각도를 직접 설정하는 방식. IK는 조인트 관절이, FK는 마지막 관절이 내 설정에 의해 결정됨.
가상 본은 다른 본의 트랜스폼(로케이션 변경)을 현재의 본 스페이스가 아닌 다른 본 스페이스에서 따르는 본. 쉽게 말하면 신체의 뼈 공간과 다른 차원의 새로운 뼈 공간을 추가해 신체의 일부 뼈를 신체의 뼈 공간이 아닌 새 뼈 공간을 따르도록 추가 지정할 수 있게 하는 기능임. 가상 본은 사실 신체 뼈 공간에도 있고, 신체를 떠나서 모든 스켈레톤에 기본적으로 설정해야하는 값임. 단지 루트 본으로 설정돼있어 FK로 동작하는 것일 뿐.
FK로만(즉 가상 본을 추가하지 않으면) 애니메이팅하면 오른쪽 움짤과 같이 팔꿈치→어깨→쇄골→척추→골반→루트본의 움직임에 손의 위치가 결정되지만, IK를 부분적으로 사용하면(가상 본을 추가하면) 총기에서 시작되는 손→팔꿈치 섹션은 총기의 움직임과 동기화되어 일명 '스위밍', 원치 않는 여분의 움직임을 제어할 수 있게 된다(왼쪽).
타깃 본과 가상 본 생성하기
타깃 본은 가상 본을 만들 때 지정하는 '따라갈 실제 본'. 가상 본은 부모를 설정할 수 있는데, 루트 본의 하위 본을 부모로도 설정할 수 있다. 가상 본의 영향 범위를 줄일 수 있다는 말. 루트 본을 부모로 설정하고 타깃 본을 왼쪽 손으로 설정하면 스켈레톤 트리 최상단(root와 같은 위치)에 VB <parent>_<target> 이름으로 본이 생긴다.

여기서 내가 착각했던 것이 가상 본은 어느 본 스페이스에 고정된 포인트라고 생각했음. 그게 아니라 애니메이션마다 가상 본은 타깃 본을 따라 움직일 수 있음.

움직일 수 있음에도 어떻게 '스위밍' 현상을 교정할 수 있었느냐? 가상 본을 사용하지 않으면 모든 조인트의 FK 계층구조에서 영향을 받아 스위밍 현상이 발생함. 가상 본을 사용하면 FK 계층구조에서 벗어나 타깃 본으로부터 역으로 운동학이 적용되어 타깃 본과 가까운 오브젝트는 스위밍 현상이 줄어들게 되는 것. 가상 본+IK를 사용한다고 움직임이 전혀 없는게 아님.
기존 IK와의 차이점
가상 본 없이 IK만 적용할 수 있음. 이는 내가 처음 생각했던 것처럼 특정 위치에 고정시키는 방식임. 이렇게 고정시키면 총기를 받치는 손의 '스위밍'은 줄어들겠지만 애디티브 애니메이션이 재생됐을 때 손이 접착제로 고정돼있기 때문에 애니메이션이 재생되는 구간동안 IK를 해제해주지 않으면 오른쪽 움짤처럼 이상하게 출력됨. 이렇게 시스템을 구성하면 모든 애디티브 애니메이션의 예외 구간을 처리해줘야하기 때문에 재사용성이 극적으로 낮아짐.
반며에 가상 본을 추가해주면 애디티브 애니메이션 재생 시에 타깃 본이 자유롭게 움직일 수 있으므로 별도의 처리 없이 IK를 유지하면서 추가적인 애니메이션도 허용할 수 있음.
가상 본 제외
블렌드 마스크로 가상 본이 애디티브 슬롯에서 영향을 받지 않게 제외해줘야 한단다.

애님 그래프에서 Layered Blend Per Bone 노드를 생성하고 Blend Mode를 Blend Mask로, Blend Masks에서 VB_BlendMask를 추가해준 뒤 애디티브 슬롯을 이 노드에 블렌드 포즈 핀에 연결해준다.


근데 왜 가상 본은 애디티브 애니메이션에 영향을 받지 않도록 제외해줘야하는 것일까?
Base Slot: 소총 재장전 애니메이션 Additive Slot: 조준 보정 애니메이션 가상 본: 재장전 애니메이션의 손 위치를 따라가는 IK 기준점 → 재장전할 때 왼손이 앞손잡이에서 떨어져 탄창으로 이동해야 함. 동시에 캐릭터는 조준 방향을 따라 머리/상체 애디티브 보정을 받고 있음.
이 때 Two Bone IK 노드의 Effector Target을 전통적인 IK-only 방식으로 '총 앞손잡이 소켓'으로 설정한다면, 재장전 애니메이션이 재생되어도 최종 계산에서 IK에 의해 왼손이 총 앞손잡이에 항상 붙어있게 됨.
반면 가상 본을 위 언급과 같이 설정해놓으면 트랜스폼은 타깃 본인 hand_l을 따라감. 이 때 재장전이 Base Slot에서 재생된다고 가정했을 때 손은 정상적으로 탄창 근처로 이동, 뽑고, 탄창 주머니로 움직임. 그런데 애디티브 보정이 얹히게 되면 척추, 어깨, 팔 계층에 영향이 생기고 실제 왼손 본이 재장전 애니메이션과 다른 위치로 밀릴 수 있음.
이런 의도하지 않은 현상을 방지하기 위해 가상 본만 블렌드 마스크로 애디티브 보정을 제외시키는 것. 애디티브 슬롯으로부터 격리시키는게 애니메이션 재생이 안되게 하는게 아니라 불필요한 보정만 끄는 작업임. 가상 본 자체는 움직이는데, 애디티브 보정으로 의도하지 않은 궤적으로 움직이는걸 방지하기 위해 제외시켜주는 것임. 좀 더 쉽게 말하면 가상 본에 해당하는 애니메이션은 보정되지 않고 순수 애니메이션 궤적을 지켜주기 위한 작업!
그리고 재장전 애니메이션은 애디티브 아님. 애디티브는 달릴 때 기우는 것처럼 '보정'을 위한 애니메이션이지 재장전같이 복잡하고 명확한 애니메이션이 아님. 대체로 애디티브 애니메이션 자체는 정적인 포즈이고(기울인 채로 고정돼있거나 머리가 뒤로 젖혀진 채로 고정돼있음) 애디티브 보정이 들어가는 찰나에만 적용됐다가 풀리는 것임
IK 구성
이 문서의 예시는 왼팔이기 때문에 손목(End Effector) → 팔꿈치(전완, lowerarm / Joint) → 어깨(상완, upperarm / Root) 체인만 신경쓰면 됨. 그래서 Two Bone IK 노드를 사용하는 것.


위 설정은 다음과 같은 뜻임
hand_l을VB root_hand_l위치로 보내라hand_l의 부모 본 스페이스를 기준으로 (-25, -50, 0)만큼 떨어진 위치를 조인트 타깃 위치로 사용한다.
여기서 조인트 타깃을 hand_l이 아니라 lowerarm_l+Bone Space로 지정할 수 있음. 그럼에도 hand_l로 지정하고 부모 본 스페이스로 굳이 지정한 것은 좀 더 정확하게 프로그래밍하기 위한 목적이라고 판단했음. hand_l의 부모 본이 lowerarm_l이 아닐 수도 있잖아(그럴 일은 없겠지만).
폴 벡터 Pole Vector란?

위처럼 아주 간단한 3 조인트 IK를 설정했다고 하자. 공간에 2개의 점과 2개의 거리만 주어져있다. 이 경우에는 아래 그림과 같이 조인트가 위치할 수 있는 지점이 무한히 있다.


이 움짤처럼 무릎이 비현실적으로 접히는 문제를 방지하기 위해선 공간에 PoleVector를 지정해줘야한다. 폴 벡터를 지정해줌으로써 공간 안에서 팔이나 다리가 접힐 평면이 하나로 정해짐. 다만 세 점이 일직선이면 평면을 만들 수 없고, 점들이 겹쳐있어도 방향을 정할 수 없음.


시작점, 끝점, PoleVector가 놓인 평면에 여전히 두 각도가 존재할 수 있는데, 이 땐 PoleVector와 가까운 각도를 선택함으로써 해결할 수 있다.

PoleVector Control과 Contraint? Control = 손잡이(점) Constraint = 규칙
이런 지식들을 총적용하면 이런 현실적인 연출이 탄생한다




