[Unity] Time

Jongmin Kim·2025년 5월 23일

Unity

목록 보기
7/19
post-thumbnail

서론

Update()FixedUpdate()에서 물리 연산을 실행하고자 할 때 Time.deltaTime을 곱해주고는 한다.
Time.deltaTime이 무엇이고 왜 필요한지와 Time 클래스의 속성들을 알아보자.



Time.deltaTime

deltaTime은 Delta + Time을 합친 단어로 시간의 차이정도로 볼 수 있다.
실제로 유니티에서의 deltaTime이전 프레임을 완료하는 데 걸린 시간을 의미한다.

Update()에서 물리 연산을 하면 프레임의 영향을 받게 된다. 이 프레임에 따라 물리 연산이 진행되는 횟수가 달라지게 되는데, 여기서 문제가 발생한다.

예를 들어, d 키를 입력하면 게임 오브젝트를 우측으로 이동시키는 예제를 작성한다고 하자.

using UnityEngine;

public class Timer : MonoBehaviour
{
    private void Awake()
    {
        Application.targetFrameRate = 30;
        // Application.targetFrameRate = 60;
    }

    private void Update()
    {
        if (Input.GetKey(KeyCode.D))
        {
            transform.position += Vector3.right;
        }   
    }
}

위의 코드를 바로 실행할 때와 주석 처리된 문장을 해제하고 실행할 때의 결과값은 달라지게 된다.
이는 Update()가 프레임의 영향을 받기 때문에 발생한다.

30프레임의 경우 게임 오브젝트의 위치에 Vector3.right30번 더하게 된다.
반면, 60프레임의 경우 게임 오브젝트의 위치에 Vector3.right60번 더하게 된다.

그렇기 때문에 이동하는 좌표가 달라지게 되는데, 이를 해결하기 위해 deltaTime을 곱해준다.

  • 30fps: Time.deltaTime의 값은 대략 0.33이 된다.
  • 60fps: Time.deltaTime의 값은 대략 0.16이 된다.

Time.deltaTime을 곱하면 결과적으로 30fps 환경이나 60fps 환경이나 거의 비슷한 결과를 도출하게 된다.



Time.timeScale

스케일(Scale)이란 단어가 크기를 의미하듯이, 유니티에서 timeScale은 시간의 크기를 말한다.
더 그럴듯하게 말하면 시간의 진행 속도, 시간의 빠르기 정도로 정리할 수 있을 것 같다.

Time.timeScale 속성은 0에 근접할수록 느려지며, 커질수록 빨라진다.


예시로 Time.timeScale을 변경하면서 sin()sin() 값만큼 이동하는 게임 오브젝트의 동작을 살펴보자.

public class Timer : MonoBehaviour
{
    private float timer;

    private void Update()
    {
        timer += Time.deltaTime;
        transform.position = new Vector3(Mathf.Sin(timer) * 5f, 0, 0);

        if (Input.GetKey(KeyCode.DownArrow))
        {
            Time.timeScale -= Time.deltaTime;
        }
        else if (Input.GetKey(KeyCode.UpArrow))
        {
            Time.timeScale += Time.deltaTime;
        }
        else if (Input.GetKey(KeyCode.RightArrow))
        {
            Time.timeScale = 1f;
        }
        else if (Input.GetKey(KeyCode.LeftArrow))
        {
            Time.timeScale = 0f;
        }
    }
}

위의 컴포넌트를 게임 오브젝트에 부착하고 실행 결과를 살펴보면 키를 누르면 게임 오브젝트가 더 빠르게 진동하고, 키를 누르면 진동이 느려지다 멈추는 것을 확인할 수 있다.



Time.unscaledDeltaTime

Time.deltaTimeTime.timeScale에 영향을 받기 때문에 의도적으로 느려지거나 빨라지도록 만들 수 있다.
반대로 의도적으로 Time.timeScale에 영향을 받지 않길 원할 때 Time.unscaledDeltaTime을 사용한다.

using UnityEngine;

public class Timer : MonoBehaviour
{
    private void Update()
    {
        Debug.Log($"deltaTime: {Time.deltaTime}\tunscaledDeltaTime: {Time.unscaledDeltaTime}");

        if (Input.GetKey(KeyCode.DownArrow))
        {
            Time.timeScale -= Time.deltaTime;
        }
        else if (Input.GetKey(KeyCode.UpArrow))
        {
            Time.timeScale += Time.deltaTime;
        }
        else if (Input.GetKey(KeyCode.RightArrow))
        {
            Time.timeScale = 1f;
        }
        else if (Input.GetKey(KeyCode.LeftArrow))
        {
            Time.timeScale = 0f;
        }
    }
}

이 코드에서 키를 누르면 deltaTime은 변하지만, unscaledDeltaTime은 변하지 않는 것을 확인할 수 있다.



Time.fixedDeltaTime

Time.fixedDeltaTimeFixedUpdate()가 실행되는 초 간격을 의미한다. 기본적으로는 0.02의 값을 가진다.
이 값은 프레임에 관계없이 일관된 물리 연산을 진행할 수 있도록 한다.

그리고 FixedUpdate() 자체가 프레임에 관계없이 정해진 횟수만큼 호출되기 때문에, FixedUpdate() 내부에서 Time.deltaTime을 사용하나 Time.fixedDeltaTime을 사용하나 동일한 결과를 가진다.

using UnityEngine;

public class Timer : MonoBehaviour
{
    private void FixedUpdate()
    {
        Debug.Log($"deltaTime: {Time.deltaTime}, fixedDeltaTime: {Time.fixedDeltaTime}");
    }
}

위의 코드를 실행하면 Time.deltaTime을 사용하나 Time.fixedDeltaTime을 사용하나 동일한 결과를 가짐을 확인할 수 있다.



Time.time

Time.time은 게임이 실행되고부터의 실행 시간을 알 수 있다.
Time.timeScale의 영향을 받으므로, 일시 정지 없이 실질적인 플레이 시간을 확인할 때 유용하다.



Time.realTimeSinceStartup

Time.realTimeSinceStartup은 게임이 실행되고부터의 실행 시간을 알 수 있다.
Time.timeScale의 영향을 받지 않으므로, 실제 플레이 시간을 확인할 때 유용하다.

profile
Game Client Programmer

0개의 댓글