게임에서 캐릭터가 움직이거나 점프를 하는 모션이 있는 것을 본 적이 있을 것이다.
유니티 엔진에서는 Animator라는 기능이 존재하는데, 조건에 따라서 에니메이션의 전환을 설정할 수 있다.
프로젝트 창에 마우스 우클릭을 하여 Create - Animator Controller하여 새 파일을 만들어준다.
만든 파일을 더블 클릭하면 이런 기본 창이 등장하는데, 휠 버튼을 눌러서 이동할 수 있다.
이렇게 생성한 Animator Controller에서 새 상태를 추가할 수 있다.
예시를 보이기 위해 아래 사진에 생성을 해보았다.
Base Layer 화면에 마우스 우클릭을 하여 Create State - Empty로 새 상태를 만들고 Inspector에서 이름을 변경한다.
또한 Inspector에서 Motion에 원하는 애니메이션을 넣으면 해당 상태에 그 애니메이션이 작동된다.
만든 상태에 마우스 우클릭을 하여 Make Transition을 클릭하면 선이 하나 따라온다.
다른 상태에 클릭을 해주면 연결이 된다. 이런식으로 상태 연결을 한다.
이런식으로 만든 Animator Controller를 애니메이션을 적용할 오브젝트에 컴포넌트로 붙여주면 된다.
코드에서 설정한 로직을 구현하기 전 몇 가지 설정을 해야한다.
왼쪽 위에 Parameters에 있는 speed는 임의로 생성한 변수이다. 코드에서는 이 speed 변수를 이용하여 애니메이션의 순서를 제어할 계획이다.
AnimatorController에서 화살표를 클릭한 후 Inspector 창을 살펴보면 맨 아래 Conditions에 임의로 생성했던 speed라는 변수가 있다. speed라는 변수의 값이 1보다 크면 WAIT->RUN 으로 변경한다는 조건을 달아놓았다.
또한 Settings 아래 시간이 표시되어있는 부분은 Animation Blending을 할 수 있다. 상태가 바뀌며 Animation이 변경될 때, 자연스럽게 변경될 수 있도록 Animation을 섞어주는 기능이다.
이제 코드로 넘어가보자.
PlayerController.cs
public class PlayerController : MonoBehaviour
{
[SerializeField]
float _speed = 10.0f;
Vector3 _destPos;
void Start()
{
Managers.Input.MouseAction -= onMouseClicked;
Managers.Input.MouseAction += onMouseClicked;
}
float wait_run_ratio = 0;
public enum PlayerState
{
Moving,
Idle,
}
PlayerState _state = PlayerState.Idle;
void UpdateMoving()
{ // 이동 상태일 때 실행되는 함수
Vector3 dir = _destPos - transform.position;
if (dir.magnitude < 0.0001f)
{
_state = PlayerState.Idle;
}
else
{
float moveDist = Mathf.Clamp(_speed * Time.deltaTime, 0, dir.magnitude);
transform.position += dir.normalized * moveDist;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 10 * Time.deltaTime);
}
// 이동하려는 플레이어에 Animator 컴포넌트를 붙여주고, 그 안에 AnimatorController 넣어줌
Animator anim = GetComponent<Animator>(); // AnimatorController 요소 가져옴
anim.SetFloat("speed", _speed); // AnimatorController의 speed 변수에 기존에 설정한 속도값을 넣어줌
}
void UpdateIdle()
{
Animator anim = GetComponent<Animator>();
anim.SetFloat("speed", 0); // AnimatorController의 speed 변수에 0을 넣음
}
void Update()
{
// 1프레임 당 한번 업데이트가 실행되는데, 실행마다 상태를 체크해서 함수를 실행한다.
switch (_state)
{
case PlayerState.Moving:
UpdateMoving();
break;
case PlayerState.Idle:
UpdateIdle();
break;
}
}
void onMouseClicked(Define.MouseEvent evt)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.red, 1.0f);
// int mask = (1 << 8) | (1 << 9);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100.0f, LayerMask.GetMask("Wall")))
{
//hit.collider.gameObject.tag;
//Debug.Log($"RayCase Camera @ {hit.collider.gameObject.name}");
_destPos = hit.point;
_state = PlayerState.Moving;
}
}
}
코드에서 AnimatorController의 speed 변수에 접근함으로써 애니메이션 상태를 변경할 수 있다.
speed 변수에서 1을 기준으로 낮으면 WAIT, 높으면 RUN 에 해당하는 애니메이션이 실행되는 것을 볼 수 있다.
'UNITY' 카테고리의 다른 글
UNITY - UI 자동화 - 게임 UI 구현 (0) | 2024.01.22 |
---|---|
UNITY - Scene (1) | 2024.01.12 |
UNITY - Camera - 마우스 클릭으로 이동하기 (0) | 2024.01.12 |
UNITY - ResourceManager (0) | 2024.01.12 |
UNITY - UI 자동화(2) - 인벤토리 구현 (0) | 2024.01.11 |