패링 게임 - 1 (애니메이션)

Labin·2025년 4월 4일

패링 게임

목록 보기
3/14

애니메이션

Fixed Duration이란?

유니티 애니메이터(Animator)에서 Fixed Duration은 애니메이션 전환(Transition) 속도를 "시간(초)" 기준으로 고정할지, "비율" 기준으로 설정할지를 결정하는 옵션이야.

✅ Fixed Duration ON vs OFF 차이
1️⃣ Fixed Duration = ON (✔ 체크됨)
애니메이션 전환이 절대적인 "초 단위"로 설정됨.

예를 들어, 전환 시간이 0.3초로 설정되면, 애니메이션 길이에 관계없이 항상 0.3초 동안 전환됨.

2️⃣ Fixed Duration = OFF (❌ 체크 해제)
애니메이션 전환이 현재 애니메이션 길이의 "비율(%)"로 설정됨.

예를 들어, 전환 비율이 0.25 (25%)이면,

길이가 2초인 애니메이션은 0.5초(2초 × 0.25) 동안 전환됨.

길이가 1초인 애니메이션은 0.25초(1초 × 0.25) 동안 전환됨.

🚀 결론
✔ Fixed Duration = ON → 항상 고정된 시간 동안 전환
✔ Fixed Duration = OFF → 애니메이션 길이에 따라 비율로 전환

💡 공격, 패링 같은 빠른 반응이 필요한 애니메이션이면 ON이 좋고,
💡 자연스러운 애니메이션 흐름(걷기 → 뛰기)이 필요하면 OFF가 더 적합해!

Can Transition To Self ON vs OFF 차이

1️⃣ Can Transition To Self = ON (✔ 체크됨)
✔ 같은 애니메이션 상태로 다시 전환할 수 있음
✔ 애니메이션이 중간에 다시 시작될 수 있음

👉 언제 필요할까?

공격(Attack) 애니메이션 연속 실행

공격 버튼을 계속 누르면 "Attack" → "Attack" 반복

반복적인 액션 (ex. 점프, 맞았을 때 리액션 등)

점프 버튼을 연타하면 "Jump" → "Jump" 바로 다시 실행 가능

2️⃣ Can Transition To Self = OFF (❌ 체크 해제됨)
❌ 현재 애니메이션이 끝날 때까지 같은 상태로 전환할 수 없음
❌ 같은 애니메이션 상태로 다시 트리거를 걸어도 무시됨

👉 언제 필요할까?

한 번 실행된 애니메이션이 끝나기 전까지 재실행을 막을 때

예: "Attack" 애니메이션이 끝나기 전에 다시 공격할 수 없도록 방지

예: "Hit" 애니메이션이 끝나야만 다시 피격 애니메이션이 실행되도록

애니메이션 Lock

애니메이션 Lock이란?
특정 애니메이션(예: 공격, 피격, 사망 등)이 재생될 때
플레이어의 입력을 무시하거나,
다른 애니메이션으로 전환되지 않도록 잠그는 상태

✅ 왜 필요한가?
1. 애니메이션 끊김 방지
예) 공격 모션 도중에 갑자기 걷기로 전환되면 어색함 → Lock으로 막음

  1. 게임 밸런스 유지
    예) 공격 도중 회피하거나 막는 건 반칙처럼 느껴질 수 있음 → Lock으로 제한
AnimatorStateInfo stateInfo = m_animator.GetCurrentAnimatorStateInfo(0);

if (stateInfo.IsTag("Lock"))
    return; // 입력 차단 또는 업데이트 중단

이렇게 하면 "Lock" 태그가 붙은 애니메이션 도중에는 다른 행동 불가 상태가 됨.

애니메이션 info

AnimatorStateInfo stateInfo = m_animator.GetCurrentAnimatorStateInfo(0);

지금 Animator에서 "어떤 애니메이션 상태가 실행 중인지",
그 상태의 재생 진행도(normalizedTime), 이름, 태그 등등을 가져오는 객체

m_animator
우리가 붙여놓은 Animator 컴포넌트야

🔹 GetCurrentAnimatorStateInfo(0)
현재 레이어 0번(기본 레이어)의 상태 정보를 가져온다는 뜻

Unity Animator는 여러 레이어를 쓸 수 있는데, 일반적으로는 0번만 씀

🔹 반환값: AnimatorStateInfo 구조체
이 안에는 아래와 같은 유용한 정보가 들어 있어:

🎯 자주 쓰는 속성들
stateInfo.IsName("이름"): 현재 실행 중인 애니메이션이 "이름"인지 확인
stateInfo.IsTag("태그"): 현재 상태에 태그가 "태그"인지 확인
stateInfo.normalizedTim:e 애니메이션이 얼마나 재생됐는지 (0.0 ~ 1.0 이상)
stateInfo.length: 애니메이션 전체 길이 (초 단위)
stateInfo.loop: 루프 여부
stateInfo.shortNameHash: 상태 이름의 해시값 (성능 최적화용)


해결한 문제

다른 애니메이션이 진행 중에는 (공격 도중에 갑자기 뒤돌기는 이상하니까) 방향전환이 진행되지 않게 Tag 에 Lock 을 넣고 이를 이용해 애니메이션 Lock을 진행.

 //Animation Lock
 AnimatorStateInfo stateInfo = m_animator.GetCurrentAnimatorStateInfo(0);
        if (stateInfo.IsTag("Lock"))
            return;

근데 Guard에도 Lock을 걸어서

        //Guard
       bool isGuarding = Input.GetMouseButton(1);
       m_animator.SetBool("Guard", isGuarding);

여기서 Bool 값이 계속 애니메이션이 진행되는 중이라 항상 Lock에 걸려서 애니메이션이 거기서 멈춤.
이를 다른 방법으로 해결하려고 개고생하다가 결국 Guard 진행 중에 바로 풀고 다른 애니메이션을 진행해도 괜찮기 때문에 Guard에서 Lock을 제거하는 방법으로 사용

using UnityEngine;
using System.Collections;

public class Bandit : MonoBehaviour {

   private Animator            m_animator;
   private Rigidbody2D         m_body2d;
   private Sensor_Hero         m_hitSensor;
   private float m_invincibleTimer = 1.0f;
   private bool                m_combatIdle = false;
   private bool                m_isDead = false;

   // Use this for initialization
   void Start () {
       m_animator = GetComponent<Animator>();
       m_body2d = GetComponent<Rigidbody2D>();
       m_hitSensor = transform.Find("HitSensor").GetComponent<Sensor_Hero>();
   }
	
	// Update is called once per frame
	void Update () {
       //Hurt
       if (m_hitSensor.State())
       {
           m_animator.SetTrigger("Hurt");
           m_hitSensor.Disable(m_invincibleTimer);
       }

       //Animation Lock
       AnimatorStateInfo stateInfo = m_animator.GetCurrentAnimatorStateInfo(0);
       if (stateInfo.IsTag("Lock"))
           return;

       // -- Handle input and movement --
       float inputX = Input.GetAxis("Horizontal");

       // Swap direction
       if (inputX > 0)
           transform.localScale = new Vector3(-1.0f, 1.0f, 1.0f);
       else if (inputX < 0)
           transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);

       // -- Handle Animations --

       //Guard
       bool isGuarding = Input.GetMouseButton(1);
       m_animator.SetBool("Guard", isGuarding);

       //Attack
       if(Input.GetMouseButtonDown(0)) {
           m_animator.SetTrigger("Attack");
       }

       //Parrying
       else if(Input.GetKeyDown("f"))
           m_animator.SetTrigger("Parrying");

       //Death
       else if (Input.GetKeyDown("e")) {
           if(!m_isDead)
               m_animator.SetTrigger("Death");
           else
               m_animator.SetTrigger("Recover");

           m_isDead = !m_isDead;
       }

       //Change between idle and combat idle
       else if (Input.GetKeyDown("g"))
           m_combatIdle = !m_combatIdle;

       //Combat Idle
       else if (m_combatIdle)
           m_animator.SetInteger("AnimState", 1);

       //Idle
       else
           m_animator.SetInteger("AnimState", 0);

   }
}

대신 가드 도중에만 좌, 우 방향전환이 가능하게 됨. 이를 해결하려면

    if (!stateInfo.IsTag("Lock")) {
        // -- Handle input and movement --  
        float inputX = Input.GetAxis("Horizontal");

        // Swap direction
        if (inputX > 0)
            transform.localScale = new Vector3(-1.0f, 1.0f, 1.0f);
        else if (inputX < 0)
            transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
    }

그냥 이런 식으로 막아버릴 수 있지만 가드 도중에는 방향전환이 자연스러워서 오히려 그냥 전환 가능하게 사용

profile
공부를 기록하는 공간

0개의 댓글