움직임 구현... 별거 아닐 줄 알았는데 예상외로 고생한 부분이 있어 기록한다.
3D 오브젝트에 애니메이션을 적용하면 Root Motion이라는 개념이 생기는데, 이게 이번에 문제를 일으켰다.
Root Motion은 3D 애니메이션이 캐릭터의 움직임을 직접적으로 제어할 수 있도록 해준다. 즉, 애니메이션 자체가 오브젝트의 Transform에 영향을 미쳐서, 캐릭터가 자연스럽게 이동하고 회전할 수 있게 해준다. 이 개념은 사실적인 움직임을 구현하는 데 유용하지만, 이를 처음 접하는 나로서는 꽤 당황스러운 부분이었다.
문제 발생: 공중부양하는 플레이어
나는 기존에 2D 게임을 개발했을 때처럼, 오브젝트에 Rigidbody와 Collider를 적용하고 이동을 스크립트로 제어하려고 했다. 하지만 돌려보니 Idle 상태에서 플레이어가 공중부양을 했다. 중력까지 적용했는데도 말이다.
알고 보니 Root Motion이 문제였다. 애니메이션이 Transform을 제어하면서 내가 스크립트로 작성한 물리 기반 이동 코드가 잘 적용되지 않았다.
해결 방법: Root Motion과 Rigidbody의 조화
Root Motion을 끄고 Rigidbody로만 이동을 제어하려 했지만, 애니메이션의 이동이 자연스럽지 않았다. 결국, Root Motion을 활용하면서도 Rigidbody를 연동하여 물리적 특성을 유지하는 방법을 선택했다.
이 과정에서 유니티의 OnAnimatorMove() 함수가 큰 도움이 되었다. 이 함수는 Root Motion과 Rigidbody를 함께 사용하여 애니메이션의 이동을 보완할 수 있게 해준다.
void Start()
{
animator = GetComponent<Animator>();
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
movement.Set(horizontal, 0f, vertical);
movement.Normalize ();
bool hasHorizontalInput = !Mathf.Approximately(horizontal, 0f);
bool hasVerticalInput = !Mathf.Approximately(vertical, 0f);
bool isWalking = hasHorizontalInput || hasVerticalInput;
animator.SetBool ("IsWalking", isWalking);
Vector3 desiredForward = Vector3.RotateTowards(transform.forward, movement, turnSpeed * Time.deltaTime, 0f);
rotation = Quaternion.LookRotation(desiredForward);
}
void OnAnimatorMove ()
{
rb.MovePosition(rb.position + movement * animator.deltaPosition.magnitude);
rb.MoveRotation(rotation);
}
코드 설명
- 애니메이션 상태 제어: animator.SetBool("IsWalking", isWalking)을 통해 키 입력이 있을 때 걷기 애니메이션을 활성화
- 이동 벡터 설정: movement.Set(horizontal, 0f, vertical)을 통해 입력된 방향으로 이동 벡터를 설정하고, Normalize로 대각선 이동 속도를 조정
- 회전 제어: Vector3.RotateTowards를 이용해 캐릭터가 부드럽게 회전하도록 설정
- OnAnimatorMove 사용: Root Motion의 이동을 Rigidbody로 반영하여 자연스러운 움직임을 구현
결론
이번에 Root Motion과 Rigidbody를 함께 사용하는 방법을 배우면서, 3D 캐릭터 컨트롤에 대해 많은 것을 배웠다. 특히 애니메이션과 물리 엔진을 균형 있게 조합하는 것이 3D 캐릭터의 자연스러운 움직임을 구현하는 핵심이라는 걸 깨달았다. 앞으로도 이 균형을 잘 맞추는 방법을 더 연구해 봐야겠다.
이제 tps fps 시점 적용시켜봐야지
'Unity > John Lemon in Nightmareland' 카테고리의 다른 글
Unity Piscine Module06 - 6. 맵 구현 (0) | 2024.08.26 |
---|---|
Unity Piscine Module06 - 5. FPS / TPS 시점 적용 (0) | 2024.08.25 |
Unity Piscine Module06 - 3. 메인 메뉴 만들기 (0) | 2024.08.21 |
Unity Piscine Module06 - 2. 구조 설정 (0) | 2024.08.21 |
Unity Piscine Module06 - 1. 과제 해석 (1) | 2024.08.21 |