Unity 13일차 학습

규수·2026년 4월 7일

개발 공부 일지

목록 보기
24/44

오늘은 애니메이션을 직접 구성하는 방법과 캐릭터의 움직임을 더 자연스럽게 만들어주는 방법에 대해 정리해보겠습니다.

1) 애니메이션 구성

애니메이션을 구성하기 위해서는 애니메이터 컨트롤러의 내부 구성을 이해해야합니다. 내용은 다음과 같습니다.

  1. 파라미터 구성: 좌측 상단에 위치한 파라미터는 스크립트와 애니메이터 사이를 연결하는 변수 역할을 수행합니다. 예를 들어 AttackTrig와 같은 트리거 변수를 설정하여 특정 동작을 실행할 신호를 보낼 수 있습니다.

  2. 애니메이션 연결:
    중앙에 위치한 화면을 나타내며 여기에서 생성한 Clip이 어떠한 조건으로 전환이 될 것인지를 구성하는 단계입니다.
    Entry, Any State를 통해 전환의 시점을 설정할 수 있습니다.

  • Entry: 애니메이터가 시작될 때 가장 먼저 진입하는 지점이며,
    기본 상태로 설정된 애니메이션(예: Poketmon_Idle)으로 즉시 연결됩니다.

  • Any State: 현재 어떤 애니메이션 상태에 있든 상관없이 특정 애니메이션(예: Dolphin_Attack)으로 즉시 전환할 수 있게 해주는 특수한 노드입니다.
    피격 상황이나 갑작스러운 공격 동작을 구현할 때 매우 유용합니다.

  1. Conditions 설정: 특정 애니메이션으로 상태가 바뀌기 위해서는 명확한 조건이 필요합니다. 예를 들어 Any State에서 Dolphin_Attack으로 이어지는 화살표에 AttackTrigger와 같은 파라미터 조건을 할당하여 사용자의 조작에 반응하도록 설정할 수 있습니다.

2) Blend Tree

블렌드 트리는 애니메이터 컨트롤러 내에서 여러 애니메이션 클립을 파라미터 값에 따라 부드럽게 혼합해주는 특수한 상태입니다.
단순히 한 상태에서 다른 상태로 전환하는 것을 넘어, 파라미터 수치에 따라 두 개 이상의 동작을 실시간으로 섞어서 보여줄 때 사용합니다.

2D의 간단한 이동방식을 예로 들면 MoveX와 MoveY라는 두 개의 파라미터를 기준으로 캐릭터의 방향을 결정할 수 있습니다.

Motion 리스트에 상, 하, 좌, 우의 애니메이션을 각각 특정 좌표(Pos X, Pos Y)에 할당합니다.

만약 입력값이 (0, 1)이라면 위쪽 애니메이션이 100퍼센트 출력되고, (0.7, 0.7)처럼 대각선 입력이 들어오면 오른쪽과 위쪽 애니메이션이 적절히 섞여서 출력됩니다.

이를 통해 수많은 방향의 애니메이션을 일일이 노드로 연결하지 않고, 단 하나의 블렌드 트리 안에서 파라미터 조절만으로 자연스러운 8방향 혹은 전 방향 이동 연출이 가능해집니다.

3) StringToHash

애니메이터의 파라미터를 제어할 때 보통 "Speed"나 "isAttack" 같은 문자열(String) 이름을 직접 사용합니다.
하지만 Update 함수처럼 매 프레임 호출되는 곳에서 문자열을 직접 쓰면, 컴퓨터는 해당 이름을 찾기 위해 매번 문자열 비교 연산을 수행해야 합니다.
이 과정이 반복되면 CPU에 불필요한 비용이 누적되어 성능 저하의 원인이 됩니다.

이 문제를 해결하기 위해 사용하는 것이 Animator.StringToHash 메소드입니다.
이 함수는 문자열을 고유한 정수(int) 값으로 변환해 줍니다.

  • 최적화 원리: 게임이 시작되는 최초 사이클(Awake)에서 문자열을 해시로 한 번만 변환하여 변수에 저장해둡니다.

  • 런타임 효율: 이후 실제 게임이 돌아가는 런타임 환경에서는 문자열 대신 미리 저장해둔 int 값을 사용하여 애니메이터와 소통합니다.
    정수 비교는 문자열 비교보다 압도적으로 빠르기 때문에 연산 성능을 크게 아낄 수 있습니다.

<style>
using UnityEngine;

public class AnimationOptimizer : MonoBehaviour
{
    private Animator anim;
    
    // 문자열을 미리 해시값으로 변환하여 저장 (읽기 전용)
    private static readonly int moveXHash = Animator.StringToHash("MoveX");
    private static readonly int moveYHash = Animator.StringToHash("MoveY");

    void Start()
    {
        anim = GetComponent<Animator>();
    }

    void Update()
    {
        float x = Input.GetAxisRaw("Horizontal");
        float y = Input.GetAxisRaw("Vertical");

        // 매 프레임 문자열 대신 int 값을 전달하여 성능 최적화
        anim.SetFloat(moveXHash, x);
        anim.SetFloat(moveYHash, y);
    }
}
</style>

오늘은 이전 시간에 만들어본 클립을 통해 애니메이션을 직접 구성하고 전환하는 방법에 대해 학습하였습니다.
또한, 학습적으로 StringToHash의 중요성에 대해 다시 한 번 깨달을 수 있었습니다.
문자열 비교의 연산 성능에 대해서는 학습하면서 종종 나왔던 얘기인만큼 최소화 시키는 방법을 구상하는 것이 좋은 개발이 될 수 있다고 생각합니다.

0개의 댓글