[Unity] 애니메이션 (Animation, Animator, Legacy, Mecanim)

세동네·2021년 7월 24일
0

유니티에서 애니메이션을 다룰 때 다양한 키워드를 마주할 수 있을 것이다. 이번 포스트에선 유니티 애니메이션에서 다소 헷갈릴 수 있는 주요 키워드를 알아보자.

· Animation

우리가 익히 알고 있는 '애니메이션'이라는 단어 자체를 유니티에서 사용하는 용어로 표현하면 '애니메이션 클립'이 될 것이다. 특정 행동을 동작으로 표현하는 일련의 변화 과정을 하나의 애니메이션 클립으로 관리한다.

애니메이션 클립이 아닌 Animation이라는 용어는 유니티에서 두 가지 용도로 사용된다.

- Animation Component

유니티 컴포넌트 중 Animation으로 레거시 애니메이션을 관리할 수 있다. 이는 Unity 4.x 시리즈와 같은 과거의 유니티 애니메이션 시스템에서 사용하는 컴포넌트로, 현 시점에서 개발되는 새로운 프로젝트에서는 사용하지 않는 것을 권장한다. 레거시 애니메이션과 과거 유니티 애니메이션 시스템에 대해선 아래에서 조금 더 자세하게 다룰 것이다.

- Animation view

위와 같이 Unity editor 상단 Window 탭을 통하거나 Project view 상의 애니메이션 에셋을 더블클릭하는 것으로 아래와 같은 Animation view를 이용할 수 있다.

Animation view에서 프레임 단위로 애니메이션 클립을 만들고 편집할 수 있는데, 기본적인 게임 오브젝트의 동작 표현과 더불어 게임 오브젝트의 위치, 머티리얼 색상, 빛의 밝기, 사운드 볼륨 등 Inspector에서 편집 가능한 모든 프로퍼티를 애니메이션하거나 임의의 값으로 변경하는 것이 가능하다.

이러한 Animation view는 Animation component와 다르게 과거의 기술이 아닌 현재의 기술임을 유의하자.

· Animator component / view

Animator view는 애니메이션 클립 전체를 정리 및 구성하는 창으로, 실제 애니메이션 클립끼리의 연결은 Animator controller가 당당하지만, 이 Animator controller를 Animator view에서 편집할 수 있다.

Animation component/view는 서로 관계없는 개념이었지만, 현재 유니티에서 공식적으로 권장하는 애니메이션 시스템인 Animator component를 애니메이션이 필요한 게임 오브젝트에 추가하고 Animator controller를 연결해 그 내용을 Animator view에서 수정하기 때문에 하나의 개념으로 볼 수 있다.

· Animator Controller

위와 같은 방식으로 Animator controller를 생성할 수 있다.

Animator controller 에셋은 FSM(유한 상태 머신)을 사용하여 재생할 애니메이션 결정 상태도를 표현하는 에셋이다. 앞서 말한 것처럼 Animator에 Animator controller를 연결하여 그 내용을 참고해 게임 오브젝트에 실제로 애니메이션을 적용하는 컴포넌트이다. 즉, Animator controller라는 애니메이션을 재생하는 방법에 대한 설계도를 이용하여 Animator라는 기계가 동작하여 실제 애니메이션을 재생하는 것이다. 애니메이션을 게임에서 재생하기 위해선 Animator controller와 Animator component 모두가 필요하다.

Project view에서 Animator controller를 생성하면 위와 같이 Animator view를 통해 파라미터와 State, transition 등을 수정할 수 있지만 이를 스크립트에서 다루는 것 또한 가능하다.

public class Test : MonoBehaviour
{
    void MakeAnimatorController()
    {
    	// AnimatorController
        AnimatorController animController = AnimatorController.CreateAnimatorControllerAtPath("Assets/Animations/ScriptAnim.controller");

        AnimatorStateMachine animStateMachine = animController.layers[0].stateMachine;
        
        // State
        AnimatorStateMachine smA = animStateMachine.AddStateMachine("smA");

        var sA = animStateMachine.AddState("sA");
        var sB = animStateMachine.AddState("sB");
        
        // Transition
        sB.AddTransition(smA);

        // Parameter
        animController.AddParameter("Test", AnimatorControllerParameterType.Trigger);
    }
    
    void Start()
    {
        MakeAnimatorController();
    }
}

위와 같이 AnimatorController, AnimatorStateMachine API를 이용하여 스크립트를 작성하고 플레이 모드로 진입하면 다음과 같이 Animator controller가 생성되고 그 안에 스크립트로 작성한 State 및 Transition이 정상적으로 연결된 것을 확인할 수 있다.

· Legacy animation

과거의 유니티 애니메이션 시스템이다. 이러한 레거시 애니메이션은 모델 자체에 애니메이션을 함께 심어둔 형태인데, 같은 구조를 가지지만 외형이 다른 여러 개의 사람 모델이 똑같은 걷기 애니메이션을 가져야 하더라도 모델마다 걷기 애니메이션이 모두 구현되어야 한다.

또한 레거시 애니메이션은 Animation component를 이용해 실제 오브젝트에 적용된다.

이와 같이 모델이 사용할 애니메이션 리스트에 연결하고 아래와 같이 코드로 상황에 맞는 애니메이션을 실행한다.

Animator anim = GetComponent<Animation>();
switch (_state)
{
	case Define.State.Die:
		break;
    case Define.State.Idle:
		anim.CrossFade("Stand", 0.1f);
		break;
	case Define.State.Moving:
		anim.CrossFade("Walk", 0.1f);
		break;
	case Define.State.Jumping:
		anim.CrossFade("Jump", 0.1f, -1, 0);
		break;
}

· Mecanim animation

현재의 애니메이션 시스템으로, 같은 구조(뼈대)를 갖는 모델들은 같은 애니메이션을 각각에 모두 구현할 필요 없이 하나의 애니메이션을 공유할 수 있다. 이것을 리타겟팅이라고 한다.

또한 이러한 애니메이션을 Animator controller라는 상태 머신을 이용하여 관리하기 때문에 직관적으로 더 많은 기능을 이용한 애니메이션 관리가 가능하다.

상태 머신에선 Parameters에 선언된 다양한 변수 값의 변동에 따라 특정 애니메이션의 실행이 결정되고, 변수 값은 코드를 통해 변경할 수 있다. 코드가 긴데, "animator."로 시작하는 부분이 애니메이션의 매개변수를 조정하는 부분이다.

void Move()
{
    animator.SetBool("isWalk", isWalk);
    Vector2 dirVec = new Vector2(hAxis, vAxis / 2);
    if (dirVec.Equals(Vector2.zero))
        isWalk = false;
    else
        isWalk = true;
    transform.Translate(dirVec * Time.deltaTime * playerStat.moveSpeed);
}

void Jump()
{
    animator.SetFloat("jumpSpeed", curSpeed);
    if (isJump)
    {
        if (playerTransform.localPosition.y > landPosition)
        {
            playerTransform.localPosition += new Vector3(0, curSpeed, 0);
            curSpeed -= Time.deltaTime / 2;
        }
        else
        {
            playerTransform.localPosition = new Vector3(playerTransform.localPosition.x, landPosition);
            isJump = false;
        }
    }
    if (jumpDown)
    {
        if (!isJump)
        {
            curSpeed = jumpSpeed * 0.1f;
            playerTransform.localPosition += new Vector3(0, curSpeed, 0);
            isJump = true;
            animator.SetTrigger("doJump");
        }
    }
}

앞서 말한 것처럼 유니티에서 공식적으로 더이상 레거시 애니메이션은 사용하지 말고 메카님 애니메이션을 사용할 것을 권장하고 있다. 초기 메카님 애니메이션은 인간형 애니메이션만 지원하여 사용이 제한적이었지만, 개발과 확장을 통해 유니티의 메인 애니메이션 시스템이 되었다. 새로운 기능도 메카님 애니메이션을 바탕으로 개발되고 지원되므로 새롭게 개발되는 프로젝트에는 메카님 애니메이션을 사용하는 것이 좋다.

하지만 그럼에도 일각에선 레거시 애니메이션을 사용하고 있는데, 적용하는 애니메이션 수가 적은 모델에 한하여 사용되고 있다. 정교한 애니메이션이 아니면서 모델이 사용할 애니메이션이 1~2개로 매우 적은 경우 레거시 애니메이션을 사용하는 것이 퍼포먼스적 측면에서 유리하다는 평가다. 그 외의 모든 경우에선 메카님 애니메이션이 더 장점이 많으니 상황에 따라 적용해보고, 프로파일러 등으로 실제 퍼포먼스를 체크하면서 가장 좋은 방법을 찾는 것이 중요하겠다.

2개의 댓글

comment-user-thumbnail
2021년 7월 24일

ㅎㅇㅎㅇ

1개의 답글