우선 Quaternion.LookRotation
메소드에 대해서 알아야 한다.
이 함수는 direction
(벡터)를 회전값(쿼터니언)으로 변경한다.
즉, direction
이라는 방향 벡터가 월드에서는 어떤 회전값인지 알아낸다.
예를 들어 (1, 0, 0) 인 방향 벡터는 오른쪽을 가리키고 있고, LookRotation
을 이용하면 월드에서 오른쪽을 바라보기 위한 회전값(rotation)을 얻을 수 있다.
이를 transform.rotation
등에 대입하면 월드에서 direction
방향을 바라보도록 회전할 수 있게 된다.
// 방향 벡터 구하기
// _destPos : 화면에서 클릭한 땅 오브젝트의 월드 좌표 값
// direction : 목표 지점까지의 방향 벡터
Vector3 direction = _destPos - transform.position;
// Slerp() : 부드럽게 회전한다.
// LookRotation(directino) : 방향 dir을 바라보기 위한 rotation 값을 구한다.
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), 10 * Time.deltaTime);
이 코드를 사용하자 두 가지 문제가 발생했다.
고꾸라졌다. 위 코드에서 _destPos
는 땅 오브젝트의 월드 좌표 값을 갖는다. 플레이어의 transform.position.y
와 _destPos.y
는 당연히 다른 값이므로, direction
방향 벡터에서 y값 또한 0이 아닌 값이 들어갔고 오류로 이어졌다. 바로 LookRotation()
이 x 축을 기준으로 회전하도록 한 것이다. 고개를 고정한 채로 위아래로만 끄덕여보자. 당신 머리의 방향 벡터 y 값이 변하고 있는 것이다. 이 상태에서의 회전값을 구하고 적용하니, 당연히 오브젝트는 앞뒤로 넘어지게 된다.
(Constraints
> Freeze Rotation
을 사용하지 않는 이유는 전 포스팅에 작성했다. Freeze Rotation
은 Rigidbody의 회전을 막는 것이고, Quaternion.LookRotation()
은 transform의 회전을 다루는 것이라 원하는대로 회전하지 않게 된다.)
direction.y = 0;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), 10 * Time.deltaTime);
direction
의 y값을 0으로 수정하니 해결됐다. 그런데 또 다른 문제가 발생했다.
원하는 방향으로 회전했지만, 마지막에 지 혼자 조금 더 회전하는 오류가 발생했다.
원인은 간단했는데, direction
이 (0, 0, 0)이 되는 순간에 Quaternion이 "비정의된 상태"에서 자동으로 대체 회전을 결정하려고 하기 때문이었다. (0, 0, 0) 이라는 방향 벡터는 존재하지 않는다.
if (direction.x != 0 && direction.z != 0)
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), 10 * Time.deltaTime);
간단하게 조건문으로 체크해줬다.
다시 실행하니 아무런 문제 없이 동작하였다.
-끝-