본문 바로가기
Game Engine/Unity

(Unity) Inverse Kinematics (역운동학)

by MeisterTJ 2022. 7. 28.

Inverse Kinematics (이하 IK) 는 운동학을 반대로 계산하는 것을 말한다.

그전에 운동학이 무엇인지 알 필요가 있다.

 

애니메이션이 가능한 모델들의 본 구조는 거의 전부 트리 형태를 가지고 있다.

Root bone에서 부터 각 부위의 끝으로 이어지게 되는데 (Joint Chain이라 한다.),

parent bone의 회전이 child bone에게 영향을 주게 된다.

 

애니메이션은 본의 회전을 미리 정해진 값으로 해서 만들게 되는데, 이를 Foward Kinematics (순운동학) 라고 한다. 

 

기본적으로 Model 의 Pose는 애니메이션의 값을 그대로 쓰면 되는데, 

같은 애니메이션을 쓰더라도 Pose가 달라야 하는 경우가 있다. 

발을 어딘가에 올려놓는다거나 (계단 올라가기), 손으로 무언가를 집는다거나.

 

IK가 적용되지 않은 애니메이션

예를 들어 위와 같이 총을 잡는 애니메이션의 경우 총의 길이에 따라 왼손의 위치가 달라져야 어색하지가 않다.

총마다 왼손이 잡아야할 포인트가 있을테고, Model의 왼손이 총의 포인트를 따라가야 할 것이다.

이렇게 하려면 왼손의 위치가 먼저 계산이 되고 그에 따라서 Parent bone이 맞춰지게 해야 하는데,

이러한 방식을 Inverse Kinematics (역운동학) 이라고 한다.

 

 

총 오브젝트에 LeftHand Empty Object를 추가해서 왼손이 위치할 position, rotation을 세팅한다.

 

 

IK를 적용할 애니메이션 레이어에 IK Pass를 켜준다.

이렇게 하면 OnAnimatorIK 유니티 이벤트 함수가 이 레이어의 번호를 인자로 받아 호출된다.

 

using UnityEngine;

public class FrInverseKinematic : MonoBehaviour
{
    public Transform leftHand;
    
    private Animator animator;
    private int layerIndex_Weapons;

    void Awake()
    {
        animator = GetComponent<Animator>();
        layerIndex_Weapons = animator.GetLayerIndex("Weapons");
    }

    private void OnAnimatorIK(int _layerIndex)
    {
        if (_layerIndex != layerIndex_Weapons)
        {
            return;
        }
        
        animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1f);
        animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1f);
        
        animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHand.position);
        animator.SetIKRotation(AvatarIKGoal.LeftHand, leftHand.rotation);
    }
}

IK를 테스트하기 위한 스크립트를 추가했다.

   

Animator의 GetLayerIndex 함수로 Layer의 Index를 가져올 수 있다.

Animator의 IK Position, Rotation의 가중치를 LeftHand 최대치로 세팅

Animator의 IK Position, Rotation을 leftHand transform의 position, rotation으로 세팅

 

작성한 스크립트를 Animator와 같은 오브젝트에 추가한다.

 

 

IK가 적용된 애니메이션

Weapons Layer의 애니메이션이 실행되면 OnAnimatorIK를 통해서 왼손의 위치가 총의 leftHand에 맞게 세팅되는 것을 볼 수 있다.