이 두 컴포넌트는 서로 다른 목적과 사용 케이스에 따라 애니메이션을 제어하는 데 사용한다. Animation은 더 간단한 애니메이션에 사용되며, Animator는 더 복잡한 애니메이션 시퀀스와 상태 관리에 사용된다.
문자열을 해시 값으로 변환하며, 이로써 성능을 개선하고 코드의 가독성을 유지할 수 있다.
Controller 폴더 밑에 TopDownAnimations.cs를 생성한다.
public class TopDownAnimations : MonoBehaviour
{
protected Animator animator;
protected TopDownCharacterController controller;
protected virtual void Awake()
{
animator = GetComponentInChildren<Animator>();
controller = GetComponent<TopDownCharacterController>();
}
}
Controller 폴더 밑에 TopDownAnimationController.cs 를 생성한다.
public class TopDownAnimationController : TopDownAnimations
{
// StringToHash : 특정 문자열을 해시값으로 변경하여 해시값을 통해 비교함. -> 문자열 비교보다 훨씬 빠르다!
private static readonly int IsWalking = Animator.StringToHash("IsWalking");
private static readonly int Attack = Animator.StringToHash("Attack");
private static readonly int IsHit = Animator.StringToHash("IsHit");
protected override void Awake()
{
base.Awake();
}
// Start is called before the first frame update
void Start()
{
controller.OnAttackEvent += Attacking;
controller.OnMoveEvent += Move;
}
private void Attacking(AttackSO sO)
{
animator.SetTrigger(Attack);
}
private void Move(Vector2 obj)
{
animator.SetBool(IsWalking, obj.magnitude > .5f);
}
private void Hit()
{
animator.SetBool(IsHit, true);
}
private void InvincibilityEnd()
{
animator.SetBool(IsHit, false);
}
}
Assets에 Animations 폴더를 생성, Player 폴더를 그 밑에 만들고 player_idle 이라는 애니메이션을 생성하자!
이후에 생성한 애니메이션을 MainSprite에 추가한 뒤, Animation Recorder를 연다. (애니메이션 더블 클릭하면 열림)
MainSprite를 선택한 상태에서 Animation Recorder에 캐릭터의 idle 애니메이션 스프라이트를 넣어준다.
애니메이션 스프라이트의 간격을 적당하게 조절한 뒤, 실행을 해보자!!
player_idle은 계속해서 실행되어야 하기 때문에 Loop Time을 체크하자.
같은 방법으로 player_run이라는 애니메이션도 추가하자.
이제 player_hit 이라는 애니메이션을 만들어 보자
플레이어가 맞는 스프라이트를 넣어준 다음, 플레이어가 맞을 때 색상 또한 변경해보자.
Add Property를 통해 SpriteRenderer.Color를 추가한다.
이후 0프레임과 3프레임에 Color를 변경해준다. 둘다 Color.g, Color.b를 0.2로 변경하여 빨간색이 되면 된다.
이제 플레이어가 공격하는 애니메이션을 만들어 보자. 다만 문제점은 현재 플레이어가 공격하는 스프라이트가 없기 때문에 공격할 때 무기가 움직이도록 만들어 볼 것이다.
Recording 버튼을 누른 후, WeaponSprite를 클릭한다. 그리고 WeaponSprite의 position X값과 Scale X값을 변경하면 애니메이션 레코더에 등록이 되는 것을 확인할 수 있다.
등록이 되는 모습.
이후에 0, 3프레임에 Position과 Scale을 원래 값으로 설정한다.
그리고 1, 2프레임에 Position과 Scale 값을 변경한다.
1프레임 ▼
2프레임 ▼
재생해서 확인해본다.
애니메이터 MainSprite를 더블 클릭하여 애니메이터 창을 연다. 그 후, player_attack을 지운다.
그후 Parameters 에서 bool IsWalking, Trigger Attack, bool IsHit을 생성한다.
그 다음, player_idle에서 Make Transition을 통해 player_run을 연결해준다. 그 반대 방향도 추가한다.
이후에 player_idle → player_run으로 가는 트랜지션을 다음과 같이 수정한다.
1. Has Exit Time을 꺼야 idle 애니메이션이 진행 중이어도 바로 run으로 넘어올 수 있다.
2. isWalking이 true가 되면 idle 에서 run으로 애니메이션이 전환된다.
다음으로 player_run에서 player_idle로 되돌아가는 트랜지션을 다음과 같이 수정한다.
1. 마찬가지로 Has Exit Time을 꺼 애니메이션이 바로 전환되도록 설정한다.
2. isWalking이 false가 되면 run에서 idle로 전환된다.
그후 player_idle과 player_hit을 전환하는 트랜잭션을 생성하고 마찬가지로 수정해준다.
이후에 애니메이터 창에서 Layers에서 layer를 추가하여 애니메이션을 분리하여 관리할 수 있다.
→ 예시로 손, 몸, 다리의 애니메이션을 각자 만들 경우, 그에 따른 layer를 분리하여 생성하면 편리하다.
우리는 layer를 추가해서 Attack layer를 만들어 스프라이트 애니메이션과 분리하여 관리할 것이다.
Attack layer를 생성한 뒤, 톱니 바퀴를 눌러 Blending을 Additive로, Weight를 1로 변경한다.
그 이후로 Create State → Empty를 생성한다. -> 평상 시에는 애니메이션이 동작하지 않도록 Empty인 상태를 유지해준다.
그리고 player_attack을 추가하여 Any State와 연결한다. -> 어떤 상태였던 간에 Attack이 트리거되면 바로 공격하도록.
Has Exit Time을 끄고, Conditions는 Attack이 트리거 될 때로 설정해준다.
그리고 player_attack과 Exit를 연결하여 공격 애니메이션이 재생되면 종료되도록 설정한다.
이제 Player에게 TopDownAnimationController를 추가해주면 된다.
이제 Loop Time을 체크해주자. player_idle과 player_run은 계속해서 실행이 되어야 하기 때문에 Loop Time을 체크해주고, 나머지는 해제하면 된다.