2D/3D 피격 모션 Blend Tree: 공격 방향에 맞는 자연스러운 애니메이션 블렌딩

피격 방향을 로컬 좌표로 변환해 2D·3D Blend Tree에 전달하고 대각선과 경계 방향에서도 자연스럽게 이어지는 피격 모션을 구성하는 방법을 정리합니다.

✓ 복사 완료!
챕터애니메이션 & 리깅
난이도중급
상태● 검토 완료
대상 엔진
UnityUnreal Engine
최종 업데이트
2D/3D 피격 모션 Blend Tree: 공격 방향에 맞는 자연스러운 애니메이션 블렌딩

피격 모션은 왜 방향별로 나눠야 할까

정면 피격 모션만 사용하면 공격이 캐릭터의 옆이나 뒤에서 들어와도 반응은 정면 피격처럼 보인다. 이 글에서는 공격이 온 방향과 반응 방향이 맞도록 모션을 나누는 구성을 다룬다.

가장 단순한 해결책은 앞·뒤·왼쪽·오른쪽 피격 애니메이션을 각각 준비하고 조건문으로 선택하는 것이다. 하지만 경계 각도에서 애니메이션이 갑자기 바뀌고 대각선 공격을 표현하기 어렵다. Blend Tree는 방향을 연속적인 값으로 전달해 인접한 모션을 섞으므로 이 문제를 줄일 수 있다.

월드 공격 방향을 캐릭터 로컬 좌표의 앞뒤와 좌우 축으로 변환하는 개념

핵심: 월드 방향을 캐릭터 로컬 방향으로 바꾸기

피격자에서 공격자로 향하는 벡터를 구한 뒤 수평면에 투영한다. 여기서는 공격이 날아온 쪽을 기준으로 앞·뒤를 구분한다. 투사체의 진행 방향처럼 공격자에서 피격자로 향하는 벡터를 입력받았다면 부호를 반대로 바꿔야 한다. 월드 방향을 그대로 Blend Tree에 넣으면 캐릭터가 회전했을 때 애니메이션 기준이 맞지 않으므로 캐릭터의 전방과 오른쪽 축에 내적해 로컬 좌표의 두 값으로 바꾼다.

  • forward: 공격이 캐릭터 앞쪽에서 왔으면 양수, 뒤쪽이면 음수
  • right: 공격이 캐릭터 오른쪽에서 왔으면 양수, 왼쪽이면 음수

캐릭터 위치를 P, 공격자 위치를 A, 캐릭터의 수평 단위 전방 벡터를 F, 수평 단위 오른쪽 벡터를 R이라고 하자. 공격이 온 쪽을 나타내는 D는 수평면에서 정규화한 A - P로 두고 Blend Tree 좌표는 다음처럼 계산한다.

x=D⋅Rx = D \cdot R y=D⋅Fy = D \cdot F

여기서 x는 좌우 축, y는 앞뒤 축이다. 공격자가 피격자와 거의 같은 위치에 있으면 방향 벡터 길이가 0에 가까워진다. 이 경우에는 마지막 유효 방향, 캐릭터 전방 또는 별도의 기본 피격 모션을 사용해야 한다.

2D Blend Tree 구성

Unity Animator에서 방향마다 클립 하나를 배치하는 이 예제는 2D Simple Directional Blend Tree를 사용한다. 같은 방향에 강도별 클립을 여러 개 배치하려면 2D Freeform Directional을 고려할 수 있지만, 이 유형에는 (0, 0)의 중심 모션도 하나 포함해야 한다. Unity 6의 2D 블렌딩 문서에 설명된 유형별 조건에 맞춰 방향별 모션을 다음 좌표에 배치한다.

모션XY
앞 피격01
뒤 피격0-1
왼쪽 피격-10
오른쪽 피격10

대각선 피격 모션까지 있다면 (-0.7, 0.7)처럼 대각선 좌표에 추가할 수 있다. 대각선 전용 모션이 없더라도 네 방향 모션을 블렌딩해 중간 방향을 만들 수 있다. 다만 모션의 몸통 회전과 발 위치가 크게 다르면 섞인 결과가 흐려질 수 있으므로 각 피격 클립의 자세와 재생 길이를 가능한 한 맞추는 편이 좋다.

flowchart TD
    A[피격 이벤트 수신] --> B[공격자와 피격자 위치 차 계산]
    B --> C[수직 성분 제거 및 정규화]
    C --> D[캐릭터 Right·Forward와 내적]
    D --> E[HitX·HitY Animator 파라미터 설정]
    E --> F[2D Blend Tree에서 방향별 모션 블렌딩]

피격 트리거와 방향 파라미터는 같은 프레임에 설정하는 것이 안전하다. 트리거만 먼저 보내면 상태 전환 시점에 이전 방향 값이 사용될 수 있다.

Unity 구현 예제

아래 예제는 Y축이 위쪽이고 캐릭터가 Y축으로만 회전해 transform.forward와 transform.right가 수평인 3D 캐릭터를 기준으로 한다. 기울어진 캐릭터에는 수평면에 투영한 전방으로 직교 좌표계를 다시 구성해야 한다. 탑다운 2D 게임에서 캐릭터가 XY 평면에서 움직인다면 축을 바꿔 같은 원리로 적용할 수 있다.

using UnityEngine;

public sealed class HitReactionController : MonoBehaviour
{
    [SerializeField] private Animator animator;

    private static readonly int HitX = Animator.StringToHash("HitX");
    private static readonly int HitY = Animator.StringToHash("HitY");
    private static readonly int Hit = Animator.StringToHash("Hit");

    public void PlayHitReaction(Vector3 attackerPosition)
    {
        Vector3 direction = attackerPosition - transform.position;
        direction.y = 0f;

        if (direction.sqrMagnitude < 0.0001f)
        {
            direction = transform.forward;
        }
        else
        {
            direction.Normalize();
        }

        float localRight = Vector3.Dot(direction, transform.right);
        float localForward = Vector3.Dot(direction, transform.forward);

        animator.SetFloat(HitX, localRight);
        animator.SetFloat(HitY, localForward);
        animator.SetTrigger(Hit);
    }
}

Animator에는 HitX, HitY float 파라미터와 Hit trigger를 만들고 피격 상태 내부에 2D Blend Tree를 둔다. 이동 중에도 피격 모션을 즉시 보이게 하려면 Any State에서 피격 상태로 들어가는 전환을 둘 수 있다. 대신 연속 피격이 가능한 게임이라면 전환 중 재시작 규칙과 무적 시간을 함께 설계해야 한다.

블렌딩이 부자연스러울 때 점검할 것

모션 길이와 기준 자세를 맞춘다

클립 길이가 다르다고 해서 Blend Tree 안에서 한 방향만 독립적으로 늦게 끝나는 것은 아니다. Unity는 블렌딩할 모션의 대응 자세가 정규화된 시간에서 일치하도록 구성할 것을 권장한다. 첫 프레임의 자세, 충격이 가장 강한 시점, 복귀 시점을 정규화된 시간 기준으로 맞추고 필요하면 클립 길이나 재생 속도를 조정한다. Unity Blend Tree 문서를 참고한다.

방향을 너무 자주 바꾸지 않는다

하나의 피격 중 매 프레임 공격자 방향을 다시 계산하면 공격자가 움직일 때 피격 자세가 흔들린다. 일반적인 근접 공격은 명중 순간의 방향을 한 번 저장하고 피격 종료까지 유지하는 편이 자연스럽다. 지속 피해나 빔처럼 방향 변화가 연출 의도인 경우에만 갱신한다.

루트 모션과 이동을 분리한다

피격 애니메이션의 루트 모션이 캐릭터를 뒤로 밀고 게임 로직의 넉백도 별도로 위치를 이동시키면 이동량이 겹친다. 피격 중에는 루트 모션을 끄고 물리 또는 캐릭터 컨트롤러가 넉백을 담당하게 하거나 반대로 애니메이션 루트 모션만 사용하도록 한 가지 방식으로 통일한다.

상체와 하체의 역할을 나눈다

달리는 중 피격을 표현해야 한다면 전신 피격 Blend Tree만으로는 이동이 끊겨 보일 수 있다. 하체는 이동 Blend Tree를 유지하고 상체에는 Avatar Mask와 별도 레이어로 작은 피격 반응을 얹는 방식이 유용하다. 강한 넉백이나 경직은 전신 모션으로 전환하고 약한 피격은 상체 레이어로 처리하면 반응의 강도를 구분하기 쉽다.

2D 스프라이트 게임에 적용하기

SpriteRenderer.sprite는 스프라이트 하나를 지정하는 참조 속성이다. 이 속성의 애니메이션을 Blend Tree에 넣는 것만으로 두 스프라이트 이미지 사이의 픽셀 보간이나 알파 교차 페이드가 구현되지는 않는다. 이미지 교차 페이드가 필요하면 별도 렌더러나 셰이더로 구성해야 하며, 픽셀 아트에서는 윤곽이 흐려지는지도 확인한다. 같은 HitX, HitY 값을 사용하되 다음 중 하나를 선택할 수 있다.

  • 네 방향 중 내적이 가장 큰 방향을 선택해 선명한 스프라이트를 재생한다.
  • 대각선 전용 피격 스프라이트를 추가해 8방향으로 구성한다.
  • 스프라이트 교체 대신 뼈나 Transform의 연속적인 움직임을 애니메이션으로 만들었다면 해당 모션을 Blend Tree로 섞는 방식을 검토한다.

카메라 기준 탑다운 2D에서는 공격 방향과 캐릭터의 바라보는 방향 중 무엇을 기준으로 할지도 정해야 한다. 캐릭터가 회전하지 않는 4방향 게임이라면 월드 축을 바로 써도 된다. 반면 조준 방향으로 회전하는 트윈 스틱 게임이라면 3D와 마찬가지로 캐릭터 로컬 축으로 변환해야 일관된 반응이 나온다.

Unreal Engine에서는 어떻게 연결할까

Unreal Engine의 Animation Blueprint에서도 원리는 같다.
피격 순간 공격 방향을 캐릭터 로컬 공간으로 변환하고 LocalHitX, LocalHitY 변수를 Animation Blueprint에 전달한다.
AnimGraph에서 2D Blend Space의 입력으로 이 값을 사용하면 된다.

강한 피격처럼 즉시 재생해야 하는 모션은 Blend Space를 포함한 상태를 타거나 피격 방향별 Montage를 선택해 재생하는 방법도 있다.
방향이 연속적으로 변해야 하거나 여러 방향 클립을 자연스럽게 섞어야 한다면 Blend Space가 적합하다.
명확한 한 방향 포즈와 타격 타이밍이 중요한 경우에는 Montage 선택이 더 예측하기 쉽다.

마무리

방향 기반 피격 Blend Tree의 핵심은 애니메이션 개수보다 좌표계다. 공격 방향을 캐릭터 로컬 공간의 좌우·앞뒤 값으로 바꾸고 명중 순간의 값을 고정한 뒤 서로 비슷한 타이밍과 자세를 가진 클립을 배치하면 네 방향만으로도 대각선 반응을 자연스럽게 만들 수 있다. 이후에는 피격 강도, 넉백, 상체 레이어를 분리해 게임의 전투 템포에 맞게 확장하면 된다.