본문 바로가기
Unity 궁둥이 쪼물쪼물

004. Enemy(적) 애니메이션 구현

by daco2020 2026. 4. 6.

Enemy의 FSM 상태(Idle, Patrol, Chase, Attack)에 맞는 애니메이션을 연결하고, 죽기(Die) 상태를 새로 추가한 과정을 기록한다.

 

 

이번 작업의 목표

 

이번 작업은 Die 상태를 추가하여 FSM 확장하고, 이미 코드에 준비되어 있던 walk, die 애니메이션을 연결할 것이다.

 

FSM 상태 변화(읽기) → 어떤 애니메이션인지 결정(계산) → Animator에 전달(적용) 이렇게 진행한다.

 

1. Animator Controller란?

유니티에서 캐릭터 애니메이션은 Animator Controller로 관리한다. 이전 작업에서는 코드로 FSM을 만들었는데, Animator Controller는 이걸 시각적으로 만드는 도구다.

  • 상태(State): 하나의 애니메이션 동작 (Idle, Walk, Attack 등)
  • 전환(Transition): 상태 간 화살표. "이 조건이면 저 애니메이션으로 바꿔라"
  • 파라미터(Parameter): 코드에서 Animator에게 보내는 신호 변수
코드 (Enemy.cs)                    Animator Controller
━━━━━━━━━━━━━━                    ━━━━━━━━━━━━━━━━
FSM 상태 변경                        애니메이션 전환
  ↓                                   ↓
animator.SetBool("walk", true)  →  idle → walk 전환 발동
animator.SetTrigger("attack")   →  → attack 전환 발동

ㄴ 비교해보면 이른 느낌이라고 보면 된다.

 

 

2. 기존 Animator Controller 확인

프로젝트에 이미 LOVEDUCK.controller가 준비되어 있었다. (이름은 LOVEDUCK이지만 엄연히 Enemy(적)이다)

 

 

 

기존에 이미 세 가지 상태가 있었다.

  • idle (주황색 = 기본 상태): 가만히 서있기
  • walk: 걷기
  • attack: 공격

과제 프로젝트에서 제공해 준 사용 가능한 애니메이션 클립들도 있었는데, 다음과 같다.

파일 용도
idle.anim 가만히 서있기
walk.anim 걷기
jump.anim 점프 (공격 모션으로 사용)
stun.anim 기절 (죽기 모션으로 활용)

 

(이 애니메이션들은 Unity 기본 제공이 아님)

 

 

3. 파라미터(Parameters) 확인

Parameters 탭을 열어보니 idle, walk, attack 세 파라미터가 있었다.

 

Bool vs Trigger - 처음에 헷갈렸던 부분

파라미터에는 여러 타입이 있다.

타입 아이콘 동작 비유 적합한 상황
Bool ☑ 체크박스 on/off 유지 전등 스위치 걷기, 달리기 (계속 유지)
Trigger ● 동그라미 한 번 발동 후 자동 꺼짐 초인종 공격, 점프, 죽기 (한 번 실행)
Float 숫자 실수값 볼륨 조절 이동 속도에 따른 블렌딩
Int 숫자 정수값 채널 번호 무기 종류 선택

 

기존에는 파라미터가 전부 Trigger로 되어있었는데, 걷기(walk)는 Bool이어야 한다!

 

왜냐하면!

 

Trigger로 걷기 애니메이션을 적용하면 걷기가 처음에 적용 되지 않거나 멈춰 있어도 계속 걷기를 하는 등, 부자연스러운 움직임이 일어난다.

 

그러므로 다음처럼 모션마다 적절한 파라미터를 사용하는 것이 좋다.

걷기 = "걷는 동안 계속" 재생 → Bool (on/off 유지)
  코드: animator.SetBool("walk", true)   // 걷기 시작
        animator.SetBool("walk", false)  // 걷기 멈춤

공격 = "한 번만" 실행 → Trigger (자동 꺼짐)
  코드: animator.SetTrigger("attack")    // 공격! 알아서 꺼짐

 

나는 기존 walk 를 지우고 Bool Parameters을 가진 walk 를 재생성하여 이 문제를 해결했다.

 

계속 유지되는 동작(걷기, 달리기)은 Bool

한 번 실행되는 동작(공격, 죽기, 점프)은 Trigger

 

일단 이렇게 이해하기로 했다.

 

 

4. Die 상태 추가하기

die 파라미터 추가

Parameters에서 +  Trigger → 이름 die
(죽기는 한 번만 실행되니까 Trigger로 설정)

die 상태 만들기

Animator 창 빈 공간 우클릭 → Create State > Empty → 이름 die

상태를 선택하고 Inspector의 Motion 항목에 stun 애니메이션을 연결했다.

 

Motion이란? "이 상태일 때 어떤 애니메이션을 재생할지" 지정하는 것.
die 상태 = stun(기절) 애니메이션을 재생.

 

 

Any State → die Transition 추가

Any State에서 die로 화살표를 연결했다.

 

설정은

  • Has Exit Time: 체크 해제 (현재 애니메이션이 끝나길 기다리지 않고 즉시 전환, 총을 맞았는데 걷다가 죽으면 어색하니까ㅎㅎ)
  • Conditions: die 트리거 (Parameters 가 Trigger 이므로 조건이 충족되면 발동)

Any State란? "어떤 상태에 있든" 이 전환이 가능하다는 뜻.
죽는 건 걷는 중이든, 공격 중이든, 언제든 발생할 수 있으니까!

 

 

 

5. Transition(전환) 조건 설정

idle → walk

 

Conditions: walk = true
→ 코드에서 animator.SetBool("walk", true)가 호출되면 이 전환이 발동

 

walk → idle

 

Conditions: walk = false (또는 idle 트리거)
→ 코드에서 animator.SetBool("walk", false)가 호출되면 이 전환이 발동

 

 

 

6. Enemy.cs 코드 수정

FSM에 Die 상태 추가

public enum State
{
    None,
    Idle,
    Patrol,
    Chase,
    Attack,
    Die  // 새로 추가!
}

상태 초기화에서 애니메이션 신호 보내기

switch (state)
{
    case State.Idle:
        _agent.ResetPath();
        animator.SetBool("walk", false);    // 걷기 애니메이션 끄기
        break;

    case State.Patrol:
        _agent.SetDestination(randomDestination);
        animator.SetBool("walk", true);     // 걷기 애니메이션 켜기
        break;

    case State.Chase:
        _agent.SetDestination(_playerTransform.position);
        animator.SetBool("walk", true);     // 추적할 때도 걷기
        break;

    case State.Attack:
        _agent.ResetPath();
        animator.SetBool("walk", false);
        // animator.SetTrigger("attack"); → 이미 Attack() 메서드에 있음
        break;

    case State.Die:
        _agent.ResetPath();
        animator.SetBool("walk", false);
        animator.SetTrigger("die");         // 죽기 애니메이션 발동
        _agent.enabled = false;             // 더 이상 이동 불가
        break;
}

죽으면 행동 중단

private void Update()
{
    _stateTime += Time.deltaTime;

    // 죽은 상태면 아무것도 하지 않음
    if (state == State.Die) return;

    // ... (나머지 FSM 로직)
}

외부에서 호출 가능한 Die() 메서드

public void Die()
{
    if (state == State.Die) return;  // 이미 죽었으면 무시
    nextState = State.Die;
}

 

나중에 총알이 적에 맞았을 때 enemy.Die()를 호출하면 된다!

 

 

7. 코드와 Animator의 관계 정리

Enemy.cs (코드)                  LOVEDUCK.controller (Animator)
━━━━━━━━━━━━━━━                  ━━━━━━━━━━━━━━━━━━━━━━━━━
State = Idle
  → SetBool("walk", false)   →  walk→idle 전환 발동 → idle.anim 재생

State = Patrol / Chase
  → SetBool("walk", true)   →  idle→walk 전환 발동 → walk.anim 재생

State = Attack
  → SetTrigger("attack")    →  →attack 전환 발동  → jump.anim 재생

State = Die
  → SetTrigger("die")       →  AnyState→die 전환  → stun.anim 재생

 

핵심은 코드의 FSM과 Animator 상태의 1:1로 대응이다.
코드가 "지금 어떤 상태야"를 알려주면, Animator가 "그러면 이 애니메이션을 재생할게"라고 반응하는 구조인 것.

 

 

 

8. 이번 작업에서 배운 것 요약

1. Animator Controller = 코드 FSM의 시각화 버전
2. 파라미터는 코드 → Animator로 보내는 신호 변수
3. Bool = on/off 유지 (걷기), Trigger = 한 번 발동 (공격, 죽기)
4. 파라미터 타입과 코드의 Set 함수가 일치해야 한다
5. Any State = 어떤 상태에서든 전환 가능 (죽기처럼 언제든 발생하는 것)
6. Has Exit Time 해제 = 현재 애니메이션 끝까지 기다리지 않고 즉시 전환
7. Motion = 상태에 연결된 애니메이션 클립

 

 

 

다음으로 발사체를 만들어 오리를 괴롭히자(?)