본문 바로가기
게임 프로그래밍/유니티(2021.3 LTS) 강좌

[유니티 기초] 오브젝트 회전과 Time.deltaTime

by 레오란다 2022. 10. 18.
반응형

1. 큐브 회전

오늘은 이전 글에 이어 Update() 에 코드를 작성해 보도록 하겠습니다.

Update() 는 매 프레임마다 호출되는 함수입니다. 유니티 에디터에서는 게임이 실행 중일 때 FPS를 확인할 수 있는 기능을 제공해줍니다. FPS를 확인하는 방법은 다음과 같습니다.

 

  • Play 버튼을 눌러 게임을 실행시킵니다.
  • Game 창에서 [Stats] 버튼을 클릭하면 "Statistics" 창이 나타나고 FPS를 확인할 수 있습니다.

FPS

위의 이미지로만 보면 Update() 함수가 1초에 약 468번 호출된다고 생각할 수 있습니다. 직접 실행해 보시면 아시겠지만 FPS 값은 고정되지 않고 계속해서 변하기 때문에 실제로 1초에 468번이 호출되지는 않습니다.

 

FPS는 게임 내에 처리해야할 오브젝트들이 많을 수록 수치가 떨어집니다. 또, 게임을 실행하는 시스템의 성능에도 크게 영향을 받습니다. 따라서, 이 기능은 게임을 플레이할 때 FPS의 변화가 어떻게 되는지 확인하는 용도로 활용하시면 좋습니다.

 

그럼 이제 Update() 함수에 코드를 작성해 보도록 하겠습니다.

이번엔 큐브를 일정한 간격으로 계속해서 회전시키는 코드를 작성해 보도록 하겠습니다. 코드는 다음과 같습니다.

 

void Update()
{
  transform.Rotate(new Vector3(0f, 0.15f, 0f));
}

 

transform.position과 마찬가지로 transform.Rotate 는 객체를 x, y, z 값만큼 해당하는 축을 기준으로 회전시킵니다. 위의 코드는 큐브를 y 축을 기준으로 0.15˚ 씩 회전시키는 코드입니다. 직접 실행해 보시면 아래와 같이 큐브가 연속해서 회전하는 것을 보실 수 있습니다.

 

y 축을 기준으로 회전하는 큐브

큐브가 연속해서 회전하는 이유는 Update 함수가 매 프레임마다 호출되기 때문입니다. 매 프레임 마다 y축을 기준으로 0.15˚ 회전하기 때문에 큐브는 빙글빙글 돌아가게 됩니다. 만약 회전 방향을 반대로 하고 싶으면 -0.15f 를 넣으면 됩니다.

 

0f 로 되어 있는 x 와 z 축에도 값을 넣어서 테스트 해보시기 바랍니다. 여러 각도로 돌아가는 큐브를 보실 수 있습니다.

 

2. Time.deltaTime

이제 큐브를 일정한 속도로 회전시키는 방법에 대해서 알아보도록 하겠습니다.

 

게임은 프레임 단위로 처리가 이루어진다고 했습니다. 60 FPS 게임이라고 해서 매초마다 항상 균일하게 60 FPS 가 되지는 않습니다. 어떤 때는 50이 나올 수도 있고 어떤 때는 63~64가 나올 수도 있습니다. 평균적으로 60 FPS 라고 생각하시면 됩니다. 그런데, 이러한 경우에 0.15f 라는 고정된 값을 넣으면 물체는 우리가 원하는 데로 일정한 속도로 회전할 수 없게 됩니다.

 

이제 산수를 조금 해보도록 하겠습니다.

 

60 FPS 가 유지될 때의 1초간 회전 각도: 60 * 0.15˚ = 9˚

45 FPS 로 떨어진 경우의 1초간 회전 각도: 45 * 0.15˚ = 6.75˚

 

이와 같이 FPS에 따라서 1초간 회전하는 각도가 달라지게 되는 문제가 발생합니다. 이를 해결하기위해 몇 가지 더 계산을 해보겠습니다.

 

먼저, 프레임 간의 시간 간격은 다음과 같이 계산됩니다.

60 FPS의 프레임간 시간 간격: 1초 / 60fps = 0.016666... 초
45 FPS의 프레임간 시간 간격: 1초 / 45fps = 0.022222... 초

 

속도, 시간, 거리의 공식에 의해서 시간 = 1초, 회전한 거리 = 9˚ 이므로 속도 = (거리 / 시간) = 9 입니다.

 

다시 공식에 의해서 [프레임간 시간 간격] (시간) 에 9 (속도) 를 곱해주면 

60 FPS 일 때의 프레임 당 회전 각 = 9 * 0.016666... ≒ 0.14994˚
45 FPS 일 때의 프레임 당 회전 각 = 9 * 0.022222... ≒ 0.19998˚

 

이와 같이 FPS 에 따른 회전 각(거리) 이 나오게 됩니다.

 

위의 결과에서 보이듯이 60 FPS 가 유지되는 구간에서는 처음에 입력했던 값인 0.15와 근사한 값이고 프레임이 떨어지는 구간에서는 그 보다 큰 0.19998˚ 이 되므로 지연된 시간만큼 더 많이 회전하게 됩니다. 이로서 큐브는 FPS의 변화와 관계없이 일정한 속도로 회전할 수 있게 됩니다.

 

다행히 유니티에서는 자체적으로 매프레임 마다 Time.deltaTime 에 프레임간 시간 간격을 계산하여 입력해 줍니다. 우리는 단지 이것을 사용만 하면 됩니다. 이제 코드를 아래와 같이 속도시간을 이용해 계산된 거리가 입력될 수 있도록 수정할 것입니다.

 

void Start()
{
  transform.position = new Vector3(0f, 3f, 0f);
  Application.targetFrameRate = 60;
}

void Update()
{
  transform.Rotate(new Vector3(0f, 9f * Time.deltaTime, 0f));
}

 

* Start() 에 "Application.targetFrameRate = 60"  추가되었습니다. 이 코드는 유니티에 사용하려는 목표 프레임율을 지정할 수 있게 합니다. 여기서 프레임율(Frame Rate)은 단지 표현하는 방식만 다를 뿐 FPS와 같은 것입니다.

 

설명이 길어졌지만 사실 시간, 거리, 속도 관계의 공식을 간단하게 이용한 것입니다. 속도 * Time.deltaTime 을 이용해 물체를 이동하거나 회전시키는 것은 게임을 개발할 때 많이 사용됩니다.

반응형

댓글