
애니메이션은 미리 모델에 심어둔 트리 구조의 본을 움직이고, 프레임 단위로 키를 먹여 저장한 에셋으로, 게임상의 모델을 정해진대로 움직이기 위해 사용한다.
본의 Transform이 child bone에게 영향을 주는 것을 기반으로 움직임을 표현하는데, 이걸 Foward Kinematics (순운동학)라고 한다.
대부분의 상황에선 애니메이션만 있어도 자연스러운 움직임을 나타낼 수 있다.
문제는 '물건을 집을 때', '양손으로 뭔가 잡을 때' 등의 상황에서 발생한다.
전자의 경우 보통 게임적 허용(시적 허용 같은 거)으로 생략한다.
우리는 게임을 할 때 음식 없이 먹는 모션만 취해도 회복이 된다거나, 문을 열 때 문고리를 잡는 게 아니라 그냥 문을 여는 듯한 동작을 재생하고 문이 열리는 등의 모습을 볼 수 있다.
플레이어들은 이런 동작들이 너무 이상한 게 아니라면 딱히 신경 쓰지 않는다.
하지만 후자의 경우는 어떨까?
FPS게임은 플레이어가 캐릭터의 양손을 계속해서 볼 수밖에 없다. 그런 상황에서 왼손이 자꾸 총을 뚫어버리고, 탄창을 공중에서 잡아 갈아끼운다면?
상당히 거슬리고 몰입감이 떨어질 수밖에 없다.
그렇다고 모든 총마다 애니메이션을 전부 따로 만든다면 애니메이터가 크게 고통받을 것이 뻔하다.
그때 등장하는 게 Inverse Kinematics(역운동학)다.
child bone의 위치를 먼저 계산하고, parent bone을 그에 맞춰 역순으로 진행하는 알고리즘이다.
// BlasterAnimInstance.h
UPROPERTY(BlueprintReadOnly, Category = "Movement", meta = (AllowPrivateAccess = "true"))
FTransform LeftHandTransform;
// BlasterAnimInstance.cpp
if (bWeaponEquipped && EquippedWeapon && EquippedWeapon->GetWeaponMesh() && BlasterCharacter->GetMesh())
{
// 캐릭터가 착용한 Weapon의 LeftHandSocket의 월드 트랜스폼을 가져온다.
LeftHandTransform = EquippedWeapon->GetWeaponMesh()->GetSocketTransform(
FName("LeftHandSocket"),
RTS_World);
// 아래 함수를 통해 받아올 위치 정보
FVector OutPosition;
FRotator OutRotation;
// LeftHandTransform을 캐릭터의 Hand_R 본을 기준으로 RelativeTransform으로 바꿔주는 함수
BlasterCharacter->GetMesh()->TransformToBoneSpace(
FName("Hand_R"), // 기준이 되는 본의 이름
LeftHandTransform.GetLocation(), // 변환하고자 하는 위치 (World Space)
FRotator::ZeroRotator, // 변환하고자 하는 회전 (World Space, ZeroRotator는 회전 없음)
OutPosition, // 출력: 변환된 위치 (Bone Space)
OutRotation); // 출력: 변환된 회전 (Bone Space)
LeftHandTransform.SetLocation(OutPosition);
LeftHandTransform.SetRotation(FQuat(OutRotation));
}
먼저 AnimBlueprint에서 사용하기 위한 LeftHandTransform을 선언하고, Tick으로 이 위치를 계속 업데이트해준다.

AnimBlueprint에서 사용할 수 있는 FABRIK 노드다.
왼쪽의 Aim Offsets는 상하좌우로 마우스를 움직였을 때 하반신은 고정하고 상반신을 돌리는 걸 보여준다.

엔드 이펙터는 영향을 주는 본, 팁 본은 영향이 시작되는 본, 루트 본은 영향이 끝나는 본이다.
그러니까 Hand_R의 위치에 따라 Hand_L의 위치를 맞추고, 그 뒤 UpperArm_L까지 위치를 역으로 계산한다는 뜻이다.

먼저 적용 전, 왼손이 어긋나는 모습이다.

이는 적용 후 오른손의 위치에 따라 왼손의 위치가 결정, 그 뒤 부모 본의 위치를 계산하는 모습이다.