나 개발자 진짜 되냐?

[ Unity 뱀서라이크 게임을 만들어보자 9 ] 애니메이션 컨트롤 본문

유니티를 공부해봐요!/초급이에요!

[ Unity 뱀서라이크 게임을 만들어보자 9 ] 애니메이션 컨트롤

Snow Rabbit 2024. 10. 11. 15:17

 

오늘은

애니메이션을 넣어보도록 하자!

 

예전에 잠시 유니티 만들 때 하긴 했었는데

좀 더 제대로 짚고 넘어가보자!


🌟 Animation 🌟

Animation 컴포넌트는

게임 오브젝트에 애니메이션을 추가하는 데 사용

애니메이션 클립을 재생할 수 있다.

 

Animation window를 통해 생성하거나 편집

간단한 애니메이션에 적합하며,

스크립트를 통해 직접 제어할 수 있고

오브젝트크기, 색상변환 등이 가능하다.

 

🌟 Animator 🌟

Animator 컴포넌트는

애니메이션의 상태를 제어하고 전환을 관리

 

Animation Controller를 사용하여

애니메이션의 복잡한 상태 기계를 구현

 

여러 애니메이션 클립을 조절하고,

애니메이션 간의 전환을 제어하고,

복잡한 애니메이션 시퀀스를

구현하는 데 적합하며,

 

캐릭터의 걷기, 뛰기, 점프 등의 애니메이션을 관리하는 데 사용

 

🌟 StringToHash 🌟

유니티 애니메이션 시스템에서 자주 사용되는 기능으로

문자열을 고유한 정수값인 해시값으로 변환해 주는 친구이다.

애니메이션 파라미터를 지정할 때 문자열 대신 해시값을 사용하면

컴퓨터 시간단축 + 애니메이션 성능 향상에 도움이 된다.

 

해쉬는 단방향이다.

그래서 문자열로 해시값을 확인할 수 있지만

해시값으로 문자열을 확인하기는 어렵다

그렇기에 다시 되돌리기도 어렵다!

 


자!

이제 본격적으로

애니메이션 스크립트를 짜보자!

 

< AnimationController.cs >

 

using UnityEngine;

public class AnimationController : MonoBehaviour
{
    protected Animator animator;
    protected TopDownController controller;

    protected virtual void Awake()
    {
        animator = GetComponentInChildren<Animator>();
        controller = GetComponent<TopDownController>();
    }
}

 

< CharacterAnimationController.cs >

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem.XR;

public class CharacterAnimationController : AnimationController
{
    // Animator.StringToHash를 통해 Animator 변수 전환에 활용되는 부분에 대한 최적화를 진행할 수 있습니다.
    // StringToHash는 IsWalking이라는 문자열을 일방향 함수인 해쉬함수를 통해 특정한 값으로 변환합니다.
    // 더 궁금하시다면 C# GetHashCode를 검색해보세요!
    private static readonly int IsWalking = Animator.StringToHash("IsWalking");
    private static readonly int IsHit = Animator.StringToHash("IsHit");

    private static readonly int Attack = Animator.StringToHash("Attack");

    private readonly float magnituteThreshold = 0.5f; //문턱을 의미

    protected override void Awake()
    {
        base.Awake();
    }

    void Start()
    {
        // 공격하거나 움직일 때 애니메이션이 같이 반응하도록 구독
        controller.OnAttackEvent += Attacking;
        controller.onMoveEvent += Move;
    }

    private void Move(Vector2 obj)
    {
        animator.SetBool(IsWalking, obj.magnitude > magnituteThreshold);
    }

    // OnAttackEvent가 Action<AttackSO>이기 때문에 Attacking이 AttackSO를 사용하지 않아도 매개변수로 가지고 있어야 합니다.
    // 이런 걸 함수(메소드) 시그니처를 맞춘다라고 합니다.
    private void Attacking(AttackSO obj)
    {
        animator.SetTrigger(Attack);
    }

    // 아직 피격부분은 없지만 곧 할 것이기 때문에 일단 둡니다.
    private void Hit()
    {
        animator.SetBool(IsHit, true);
    }

    // 아직 피격부분은 없지만 곧 할 것이기 때문에 일단 둡니다.
    private void InvincibilityEnd()
    {
        animator.SetBool(IsHit, false);
    }
}

주석 확인해 주시면 됩니다 

 

 


자, 이제 애니메이션을 만들어보자

에셋 파일에 Animation/Player 폴더 생성

 

그 플레이어 폴더 안에서

Create 클릭 > Animator Controller 생성

 

다음에 우리 인스펙터창에서

Animator 컴포넌트 추가하고 Controller에 적용

 

다음에 

Ctrl6번 누르면

애니메이터 창이 뜨는데

create 해줘서 이름은

player_idle

 

여기서 중요한 건 녹화모드 키고 진행!

 

스프라이트에서 파일을 눌러주면

그파일의 경로가 뜨게 된다.

우리는 여기서 idle만 4개 가져와서 녹화 위에 얹는다.

움직임을 위해 0.6까지 당기고

 

여기 눌러서 

Show Simple Rate

해주면 왼쪽에

 

샘플이 뜬다

12로 설정!

 

제일 중요한 건 

MainSprite의 Color를 흰색으로 바꿔주어야 한다.

색을 입혀두어야 한다!!

 

자 이제 다른 걸 만들어보자

새로 만들 땐

역삼각형 눌러서 새로운 클립생성!

 

player_run도 같은 방식으로 진행

대신 0.6까지 늘리지 말고

복사하면 끝나게

보통 3에서 끝난다.

 

다음

player_hit을 하는데

한 대 맞은 거라서

색도 빨간색으로 해주고

샘플 12에 해주고

녹화 키고

0에 해주고 색 변경 해준 다음에

그대로 복사해서

2로 가서 복사해 준다.

2초 동안 유지되는 모습을 보여주기 위함이다.

이렇게!

 

 

다음

player_attack

여기서는 활이 띠용 띠용 움직인다.

 

띠용 띠용하게 하기 위해서는

transform을 건드려줘야 한다.

0초에서는

0.5 / 0.7 / 1

 

2초에서는

0.8 / 0.7 / 1

 

4초에서는

0.7 / 0.7 / 1

 

하고 녹화종료!

 

하면 끝!

 

애니메이션에서

공격하는 거랑 때리는 건

눌렀을 때 한 번만 되어야 하기 때문에

인스펙터창에 loop time을 체크해제 해주어야 한다.

 

다음

윈도 > 애니메이션 > 애니메이터 해주면

이런 창이 뜬다.

 

우리는 이 창에서

먼저 attack를 빼줄 것이다.

왜냐면 얜 화살이 움직이기 때문ㅎ

지워주고

 

왼쪽에 파라미터 있죠.

거기 눌러서 + 해서

세 친구를 추가해 준다.

IsWalking(Bool), Attack(Trigger), IsHit(Bool)

 

다음 주황색 idle에서 오른쪽키

Make Transition > run에 붙이고

 

Has Exit Time 체크 해제,

( 바로 실행할 거 기 때문 )

Condition 추가

Transition Duration 0으로 설정

( 바로 실행할거기 때문 )

 

그다음에 이제 반대로

run에서 idle로 가는 방향도 찍어주어야 한다.

 

반대도 값은 또 같고

마지막에 컨디션만 false로 바꿔주어야 한다.

꺼져야 하니까!

 

hit도 같은 방식으로 해주되

마지막에 hit에서 idle로 돌아갈 땐

바로 휘돌아가는 건 좀 이상하니까..

exit time을 1로 해주고

다른 값은 동일하게 해 준다!

 

다음에

layer로 와서

새로운 레이어를 만든다

그리고 애니메이션에서

attack를 쭈욱 드래그해 주면

주황 네모가 생긴다.

 

다음에 빈 노드도 하나 추가한다

마우스 오른쪽 create state > empty

 해주고 그 빈 노드에 우클릭

 

 

노란색으로 바꿔주고

새로운 빈통을 어택이랑 연결하고

기존에 있던 플레이어 어택이랑 exit 랑 엮어준다.

 

 

이렇게 해주면 되고

new > player_attack 에는

exit time 해제

duration 0

그리고

conditions 가 attack가 시작되는 즉시로 해주면 된다.

 

다음에 attack에서 exit는 

exit time 1

duration 0

해주면 된다.

 

그리고 마지막으로

layer에서 만들어주었던 어택친구를

additive로 바꿔준다.

 

이러면 신나게 움직여진다!!!

 

자 이제

적을 구현해 보자!!