Unity | Rotate 와 Quaternion.Euler 로 시계 구현

Clean·2025년 4월 16일

Unity

목록 보기
5/24
post-thumbnail

처음 시계 오브젝트를 만들 때, Update()에서 시간과 분 값에 따라

자식으로 있는 HourBase, MinuteBase 의 회전값을 바꿔주면 되지 않을까?

라는 생각으로 그나마 알고있는 함수인 transform.Rotate() 로 회전값을 지정해줬다.

하지만...


Rotate() 로 시도

[Range(0, 12)]
public int hour;
[Range(0, 60)]
public int minute;

public GameObject hourBase;
public GameObject minuteBase;

void Update()
{
    if (hour == 12)
        hour = 0;
    if (minute == 60)
        minute = 0;
        
	hourBase.transform.Rotate(0, hour * 30, 0);
	minuteBase.transform.Rotate(0, minute * 6, 0);
}

시간설정은 인스펙터창에서 하게 했고, Range 로 시간은 0 ~ 12, 분은 0 ~ 60 로 제한을 뒀다.

시간을 3시 15분으로 지정하고 실행해보면...

시침과 분침이 계속 움직이는 것을 볼 수 있다.


왜 계속 움직일까?

Debug.Log(hourBase.transform.rotation);
Debug.Log(minuteBase.transform.rotation);

Rotate() 함수는 축을 기준으로 회전하는 함수다.

Rotate()는 오브젝트의 회전값을 지정해주는 것이 아닌,

현재 회전값에 인수로 넣은 값을 더하는 방식이다.

즉, hour * 30, minute * 6 값을 더해주기 때문에

Update()가 실행될 때마다 시침과 분침의 회전값이 바뀌는 것이다.


Quaternion.Euler() 로 시도

그렇다면 인스펙터창에서 시간과 분을 지정했을 때,

어떻게 해야 시침과 분침이 고정되게 할 수 있을까?

Update() 방식으로 구현할 경우,

회전값을 더해주는 것이 아닌 회전값을 지정해주는 것,

즉, transform.rotation에 회전값을 할당하는 방법이 필요하다.

void Update()
{
	if (hour == 12)
		hour = 0;
	if (minute == 60)
		minute = 0;

	hourBase.transform.localRotation = Quaternion.Euler(0f, hour * 30f, 0f);
	minuteBase.transform.localRotation = Quaternion.Euler(0f, minute * 6f, 0f);

	Debug.Log(hourBase.transform.rotation);
	Debug.Log(minuteBase.transform.rotation);
}

시간을 3시 45분으로 지정하고 실행해보면...

Update()가 계속 호출되지만 시침과 분침이 고정되어 있다.

Rotate()로 회전값을 누적시키는게 아닌 rotation회전값을 지정해주고 있기 때문이다.


rotation

rotationQuaternion 타입의 값이 필요한데

Quaternion.Euler() 는 float 3개나, Vector3()를 받아 Quaternion 타입의 값을 반환해주는 함수다.

현재 구현한 시계는 시침과 분침의 transform.rotation y값만 변하면 되기 때문에

  • Quaternion.Euler(0f, hour * 30f, 0f)
  • Quaternion.Euler(0f, minute * 6f, 0f)

위의 두 값을 할당해준 것이다.

하지만 코드는 rotation이 아닌 localRotation에 할당하고 있다.


localRotation

localRotation부모 오브젝트 기준의 회전값이다.

부모인 ClockBase 의 로테이션은 (-90, 0, 0) 이고

자식인 HourBase, MinuteBase의 로테이션은 (0, 0, 0) 이다

이 상태에서 localRotation 에 (0, y, 0)을 할당하면,

부모를 기준으로 y만 회전하기 때문에 x값을 따로 지정해주지 않고도 회전하는 것이다.


ex) hourBase.transform.rotation = Quaternion.Euler(-90f, hour * 30f, 0f);

만약 자식의 transform.rotation에 값을 넣어주려면 (0f, hour * 30f, 0f) 이 아니라

부모의 회전값을 생각해서 값을 넣어주면 정상적으로 작동한다.


360도로 돌기만 하는 MSW와 달리 Unity 3D에서는 X, Y, Z축이 있어서

Quaternion으로 좀 더 다양하고 복잡한 방향으로 회전할 수도 있지만,

그만큼 더 수학적인 계산이 필요할텐데 ㅠㅠ 어렵다

rotation
Rotate
Quaternion.Euler

0개의 댓글