이 글은
https://www.inflearn.com/course/유니티-게임-프로그래밍-에센스
강의를 요약한 강의노트 입니다.
유니티를 처음 접하시는 분들이거나 좀 더 기반을 다지고 싶으신 분들에게 👍강력하게 추천합니다.
오브젝트의 회전은 vector로 지정할 수 없다.
에디터에서는 x, y, z로 보여주기 때문에 vector로 착각할수 있지만
유니티에서 직관적으로 보기 편하도록 제공한것이다.
❌transform.rotation = new Vector3(30, 30, 30);
그럼 어떻게 사용해야하나
답은 쿼터니언을 사용하는 것
오일러각이란, 회전하기 전 상태에서 회전한 다음 상태가 되려면
세 번(x축, y축, z축)나누어 각각 얼마만큼 회전하면 되는지 계산하여 회전을 표현하는 방식입니다.오일러각의 문제점
짐벌락 :
3d오브젝트의 x, y, z축 중 한 축이 90도로 이전과 이후의 축 중 하나가
겹쳐 상실되는 현상
ex) z축으로 90도 회전했을때 이전의 y축이 x축과 겹쳐 차원 하나가 상실된다.
이를 해결하기 위해 사용하는 것이 쿼터니언이다.
- 쿼터니언은 x, y, z, w를 다뤄 4차원이다.
- 쿼터니언을 사용하면 오브젝트를 한번의 연산으로 회전시키기 때문에 짐벌락현상이 발생하지 않고 90도 회전을 수행할 수 있다.
- 쿼터니언은 계산이 복잡하므로 유니티는 내부에서 쿼터니언으로 처리하지만 인스펙터 창에서는 트랜스폼 컴포넌트의 회전을 vector3로 다룬다.
- 우리가 직접 유니티의 쿼터니언 내부를 조작할 수는 없다.
우리가 해야할 것은 Vector3를 쿼터니언으로 다룰 수 있어야 한다.
Code
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SetRotation : MonoBehaviour
{
int i = 0;
Quaternion a = Quaternion.Euler(new Vector3(45, 0 ,0));
Quaternion b = Quaternion.Euler(new Vector3(0, 90 ,0));
Quaternion c = Quaternion.Euler(new Vector3(0, 0 ,60));
void Update()
{
for (; i < 3; i++)
{
if (i == 0)
transform.rotation *= a;
if (i == 1)
transform.rotation *= b;
if (i == 2)
transform.rotation *= c;
}
}
}
오브젝트의 Transform의 Rotation을 보면 45, 90, 60이 아니다.
Code
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SetRotation : MonoBehaviour
{
void Start()
{
Quaternion newRotation = Quaternion.Euler(new Vector3(45, 90, 60));
transform.rotation = newRotation;
}
}
쿼터니언을 사용했더니 45, 90, 60으로 회전된 모습을 볼 수 있다.
방향 혹은 오브젝트를 주면 주면 해당 위치를 보도록 회전을 시켜주는 함수
오브젝트의 얼굴은 z축이다.
void Start()
{
Vector3 direction = targetTransform.position - transform.position;
//Quaternion newRotation = Quaternion.Euler(new Vector3(45, 90, 60));
Quaternion targetRotation = Quaternion.LookRotation(direction); // 직접 new Vector3로 넣어도 된다.
transform.rotation = targetRotation;
}
중간값, 두개의 값을 주면 두 값의 사이값을 리턴해주는 함수
Lerp(a, b, percent) a와 b사이의 값중 percent의 지점을 리턴
ex)
0.5f => a = 30 b = 60=> return 45
0 => return a
1 => return b
void Start()
{
Quaternion aRotation = Quaternion.Euler(new Vector3(30, 0, 0));
Quaternion bRotation = Quaternion.Euler(new Vector3(60, 0, 0));
Quaternion targetRotation = Quaternion.Lerp(aRotation, bRotation, 0.5f);
transform.rotation = targetRotation;
}
회전을 더 시키는 방법
void Start()
{
Quaternion targetRotation = Quaternion.Euler(new Vector3(45, 0, 0));
transform.rotation = targetRotation;
transform.Rotate(new Vector3(30, 0, 0));
}
쿼터니언을 Vector3값으로 리턴
Rotate처럼 활용하기
1. 오브젝트의 트랜스폼으로부터 rotation을 쿼터니언으로 저장
2. eulerAngles를 사용해 Vector3로 바꾸기
3. 회전할 만큼 Vector3연산하기
4. 쿼터니언으로 변환한 후 다시 오브젝트에 적용시키기
void Start()
{
Quaternion originalRotation = transform.rotation;
Vector3 originalRotationInVector3 = originalRotation.eulerAngles;
Vector3 targetRotationVec = originalRotationInVector3 + new Vector3(30, 0, 0);
Quaternion targetRotation = Quaternion.Euler(targetRotationVec);
transform.rotation = targetRotation;
}
쿼터니언은 기본적으로 행렬로 이루어져있다.
행렬은 성분의 값을 증가시킬때 곱셈을 사용한다.
그래서 곱셈으로 연산을 해야 더 회전을 시켜줄 수 있다.
void Start()
{
Quaternion originalRotation = Quaternion.Euler(new Vector3(45, 0, 0));
Quaternion plusRotation = Quaternion.Euler(new Vector3(30, 0, 0));
Quaternion targetRotation = originalRotation * plusRotation;
transform.rotation = targetRotation;
}
Rotate함수로 회전을 시킬 경우
원하는 각도만큼 회전이 안되는 경우가 있다.
이유는 회전은 오브젝트 중심 즉 로컬을 기준으로 회전하기 때문에 발생하는 문제다.
아래는 Vector3(30, 45, 60)을 x축으로 30도 회전시킨 예시이다.
왼쪽
Rotate함수를 사용해 30도 회전시킨 모습, Vector3(40.5053596,79.7150192,80.5376892)
오른쪽
에디터에서 직접 30도 회전시킨 모습,
Vector3(60, 45, 60)