제목으로는 어떤 포스팅인지 궁금할 것이다.

 

우리는 유니티에서 회전값을 받아오거나 셋팅할때 Quaternion 자료형을 쓴다.

 

평소때는 부모의 회전값을 고려할 필요가 없고, 있더라도 localRotation을 씀으로써 별 어려움 없이 쓸 수 있다.

하지만, 근래 모바일의 자이로 센서 회전값을 카메라에 적용해야 할 필요가 있어, Input.gyro.attitude 값을 그대로 카메라에 넣었더니, 당연하게도 정상동작을 하지 않았다.

 

첫번째 난관으로는 오른손 좌표로 넘어오는 자이로 회전값을 왼손좌표를 쓰는 유니티 좌표로 변환하는 곳

두번째 난관으로는 변환 후 카메라에 해당 회전값을 적용하는 곳이었다.

여기까지는 단순히 자이로 공간 -> 유니티 카메라 공간 일 뿐이므로, 약간의 삽질은 있었지만, 샘플 프로젝트에서 정상동작 확인 후 실 프로젝트에 적용하게 되었다.

 

하지만 역시나 되지 않았다.

몇번의 구글링을 해보니 카메라의 부모 오브젝트를 하나 만들고 그녀석의 회전값을 (90f, 180f, 0f) 해놓고 자이로 값을 카메라의 localRotation에 넣으라신다.

 

하지만 나는 부모의 부모의 회전값도 실시간으로 건드려야 하기 때문에 로컬회전값 따윈 필요하지 않아서, '좋아 얘를 월드회전으로 바꿔야지' 하면서 호기롭게 부모의 월드 Quaternion * 자이로 회전값 을 카메라의 월드회전값에 적용했다.

결과는 비루했고, 원인을 찾아 해결은 햇지만 추후 다시 쿼터니언을 다룰 일이 있을것 같아 알게된 몇가지 명제에 대해 정리하고자 한다.

 

  • transform.rotation : Quaternion.Inverse(transform.parent.rotation) * transform.localRotation
  • 쿼터니언 A, B 간의 차이 : A * Quaternion.Inverse(B)  쿼터니언의 곱은 교환법칙이 성립하지 않는다. 순서 주의
    • A에서 B로 가기 위한 회전값으로도 간주할 수 있다.
  • A 쿼터니언에 회전값 B를 추가 : B * A
    • 주의하자. 회전값을 추가할때는 항상 추가하고자 하는 값을 먼저 곱한다.

 

이를 이용해 자이로 센서값을 카메라의 월드회전에 적용하기 위한 코드는 다음과 같다.

camera.rotation = Quaternion.Inverse(Quaternion.Euler(90f, 180f, 0f)) 
					* Input.gyro.attitude 
					* new Quaternion(0f, 0f, 1f, 0f);

 

 

포지션은 부모의 위치를 쭉 순서대로 더하면 나의 월드 위치를 알 수 있는 것관 다르게 회전은 부모의 회전 역행렬을 먼저 곱해야 나온다는 사실을 잊지 말아야겠다.

 

 

'Unity' 카테고리의 다른 글

Batch 및 SetPass Calls  (0) 2020.12.03
rigidbody, collider 개념 및 정리  (0) 2020.10.08
IL2CPP  (0) 2020.09.29
Addressables  (0) 2020.07.28
Mobile 최적화  (0) 2020.06.12

+ Recent posts