Unity Update와 Time

SV's DEV·2025년 7월 15일
0

Unity 최적화

목록 보기
2/3
  • Unity에서 Time.timeScale을 활용하면 게임의 속도를 조절하거나 정지시키는 것이 가능합니다. 하지만 timeScale을 활용하면 animation에도 영향을 받기 때문에 UI가 멈추기도 합니다. 그래서 회사마다 Update와 Time을 따로 관리 해 주는 곳도 있습니다. 이렇게 하면 자기가 원하는대로 관리 할 수 있는 장점이 있지만 새로 프로젝트에 투입 된 사람에게는 알아야 할 것이 많아지고 뜻하지 않은 버그도 많이 발생하게 됩니다. 그래서 저는 무작정 새로 만들기 보다는 엔진이나 기존의 시스템을 최대한 이해하고 활용하며 부족한 부분을 개발하는 것을 선호합니다. 그러면 Update의 흐름과 여러가지 Time에 대해 알아보겠습니다.

1. Unity Update

  • 스크립트 라이프 사이클
    스크립트 라이프 사이클

  • FixedUpdate : FixedUpdate는 Project setting/Time/Timestep의 값에 따라 호출되기 때문에 프레임과 무관합니다. 움직임을 계산 할 때 Time.deltaTime을 곱해 줄 필요가 없습니다. FixedUpdate 이후 모든 물리 계산이 실행되기 때문에 보통 여기에서 물리와 관련된 코드를 작성 해 줍니다.
    또한 timeScale에 의존적입니다. 자세한 설명은 Time과 함께 설명하도록 하겠습니다.

  • Update : 프레임 당 한번 호출 됩니다. Application.targetFrameRate로 초당 프레임을 지정할 수 있습니다. 그리고 timeScale과 무관하게 호출됩니다.

  • LateUpdate : Update가 끝난 후 프레임 당 한번 호출 됩니다. 일반적으로 Update에서 캐릭터가 움직이고 난 후 거기에 맞게 카메라가 이동 및 회전을 할 수 있도록 3인칭 카메라에 사용합니다.

참고 링크 : 이벤트 함수의 실행 순서

2. Unity Time

  • Unity Time과 Update 로직

  • deltaTime : 마지막 프레임이 완료된 후 경과한 시간을 초단위로 반환 합니다. Readonly속성을 갖습니다. FixedUpdate에서는 FixedUpdate경과 시간이기 때문에 fixedDeltaTime과 같은 값이 나옵니다.

  • time : 시작시점부터 deltaTime의 합을 나타냅니다.

  • fixedDeltaTime : 고정 타임스텝 루프 간격을 제어합니다. 이 값에 따라 FixedUpdate가 호출되며 게임 내에서 수정이 가능합니다.

  • maximumDeltaTime : deltaTime의 상한입니다. 만약 어떤 시점에서 딜레이가 생겼을 때 실제 딜레이 시간이 maximumDeltaTime보다 큰 경우 deltaTime은 maximumDeltaTime이 되고 이를 Time에 증가 시킵니다.

  • unscaledDeltaTime : 이름 그대로 timescale에 영향을 받지 않는 deltaTime입니다.

참고 링크 : Unity Time

3. 게임 속도 변경

  • timeScale을 수정하면 게임 속도를 변경 할 수 있습니다. timeScale이 어떻게 게임 속도에 영향을 주는지 확인해 보겠습니다. 우선 Update는 timeScale값에 상관없이 Application.targetFrameRate를 기반으로 호출 됩니다. 기본값은 -1로 되어 있는데 이 기본 값은 각 플렛폼 마다 다르게 설정되고 vSync와도 연관이 되어 있는데 자세한 내용은 유니티 문서를 참고하고 넘어가도록 하겠습니다.
    실제로 Update에서 deltaTime을 확인 해보면 (실제 경과시간 x timeScale)의 값으로 표시 됩니다. timeScale이 0.5일 경우 실제로 1초가 지났다면 게임에서는 시간이 (1 x 0.5) 즉 Time.time은 0.5이고 deltaTime도 (실제경과시간 x 0.5)가 되므로 timeScale 만큼 실제보다 시간이 느리게 흘러가는 것을 알 수 있습니다. Update 내에서 이동을 구현 한 경우 deltaTime을 곱해 주면 timeScale의 영향을 받게 때문에 그만큼 천천히 가게 됩니다. 마찬가지로 애니메이션 같은 경우에도 일반모드에서 deltaTime의 영향을 받으므로 timeScale만큼 천천히 재생됩니다.
    이동을 FixedUpdate에서 구현한 경우 호출이 timeScale의 영향을 받습니다. timeScale을 0.5로 하면 그만큼 느리게 호출 되기 때문에 이동 속도 또한 느려지게 됩니다. 하지만 이동하는 주기 역시 느려져서 끊겨 보이고 물리 계산 역시 느려지기 때문에 일정한 속도를 유지하고 싶다면 timescale을 변경할 때 아래와 같이 fixedDeltaTime도 수정하여 게임 내의 시간이 빠르거나 느리게 흘러가도 FixedUpdate는 일정하게 호출되도록 유지 할 수 있습니다.
float fixedDeltaTime;

void Awake()
{
	this.fixedDeltaTime = Time.fixedDeltaTime;
}

void SetTimeScale(float timeScale)
{
	Time.timeScale = timeScale;
	Time.fixedDeltaTime = this.fixedDeltaTime * Time.timeScale;
}
  • FixedUpdate는 프레임과 무관하므로 deltaTime을 곱해 줄 필요가 없습니다. 하지만 timeScale을 위와 같이 수정하였을 때 FixedUpdate을 일정하게 호출되기 때문에 속도도 일정하게 유지됩니다. 속도에 변화를 주고 싶다면 timeScale값도 곱해줍니다. 그러면 FixedUpdate호출이 Update호출 보다 줄어들어 끊겨 보이는 현상도 줄일 수 있고 물리 계산 역시 일정하게 유지 시킬 수 있습니다. 반대로 속도를 증가시켜 2배속이나 4배속으로 실행 할 경우 이동 속도는 증가하지만 물리연산은 일정하게 유지되기 때문에 관통하는 경우가 생길 수 있습니다. 이런 경우에는 FixedUpdate도 빠르게 호출해야 하기 때문에 fixedDeltaTime을 수정 하지 않아야 문제를 해결할 수 있습니다. 하지만 그만큼 부하를 줄 수 있기 때문에 게임에 맞게 선택 할 필요가 있습니다.

4. 일시 정지

  • 맨 처음 이야기 했던 일시 정지에 대해 이야기 하겠습니다. 보통 Unity에서 일시 정지를 하고 싶으면 timeScale을 0으로 만듭니다. 그러면 timeScale과 관련된 모든 동작이 멈추게 됩니다. 기본적인 UI나 버튼 애니메이션 같은 경우 timeScale과 무관하기 때문에 제대로 동작을 하지만 직접 만든 애니메이션 같은 경우 기본적으로 timeScale에 의존적이기 때문에 같이 멈추게 됩니다. 그래서 애니메이션 같은 경우 timeScale과 무관하게 작동하도록 Update Mode를 Unscaled Time으로 수정 할 수 있습니다. 그리고 Update 같은 경우 timeScale과 무관하게 호출이 되기 때문에 timeScale이 0이라도 계속 호출되어 의도치 않은 동작을 할 수 있기 때문에 적절한 Update를 상황에 맞게 사용할 필요가 있습니다.

0개의 댓글