일시정지를 눌러도 이펙트만 계속 움직이는 까닭

게임에서 일시정지를 눌렀는데도 불구하고 가장자리 이펙트나 불꽃 파티클이 계속 움직이는 것을 본 적이 있을텐데요. 버그처럼 보일 수 있지만 사실은 아닙니다.

이건 개발자가 의도적으로 설계한 결과이고 그 뒤에는 “게임 시간이 하나가 아니라 두 개”라는 숨겨진 사실이 있습니다. 이번 글에서 이 구조를 파이썬 시뮬레이션을 통해 검증해보겠습니다.

게임 속 시간은 두 개다

게임 엔진은 대개 시간을 두 개로 나눠서 관리를 하는데요. 하나는 슬로우 모션이나 일시정지의 영향을 받는 “스케일된 시간”이고 다른 하나는 그런 효과들과는 무관하게 실제 시계 그대로 흘러가는 “스케일 되지 않는 시간”입니다.

물리 연산이나 캐릭터 이동처럼 게임 진행에 직접 관여하게 되는 로직은 일반적으로 스케일된 시간을 사용하고 배경 연출이나 일시정지 메뉴의 애니메이션처럼 게임 진행과는 상관없이 계속 사용자에게 보여야 하는 요소들은 스케일되지 않는 시간을 사용합니다.

일시정지가 하는 일

이 두 가지 구분이 어떻게 실제로 작동하는지는 유니티의 공식 문서에 정확히 나와 있습니다. 유니티 스크립팅 API 문서는 Time.timeScale을 “게임 내 시간이 실제 시간에 대해 진행되는 속도”로 규정하고 있으며 이 세팅값이 0으로 설정되면 “모든 함수가 프레임 레이트에 독립적이면 애플리케이션이 일시정지된 것처럼 작동한다.”라고 안내하고 있습니다.

정리하자면 일시정지 버튼을 눌렀을 때 실제로 발생하는 일은 화면이 멈추는 것이 아니라 스케일된 시간의 흐름 속도가 0이 되는 것 뿐이라고 할 수 있습니다.

이펙트는 왜 멈추지 않을까?

그럼 왜 특정 이펙트는 이 영향을 받지 않는 걸까요? 유니티의 파티클 시스템에는 useUnscaledTime이라는 속성이 있는데 공식 문서는 이 속성이 활성화되면 파티클 시스템이 “unscaled delta time을 사용하여 시뮬레이션”되며 “게임이 일시 정지 되어 Time.timeScale이 0으로 설정된 상황에서도 시각 효과를 계속 재생하고 싶을 때 유용하다”고 안내하고 있습니다.

개발자가 이 옵션 하나를 활성화하는 순간 그 이펙트만 일시정지의 여파에서 벗어나 계속 움직일 수 있게 되는 것입니다.

코드로 실현하기

이 동작을 파이썬을 이용해서 재현해봤습니다. 60fps 루프를 돌리면서 1초 시점에 일시 정지(timeScale을 0으로 설정)가 걸린다고 설정을 하고 스케일된 시간으로 움직이는 오브젝트와 스케일 되지 않는 시간으로 동작하는 이펙트 각각의 누적 진행량을 3초 동안 체크하고 기록했습니다.

결과는 예상과 완벽히 일치하였는데요. 일시정지 시점인 1초까지는 두 값이 똑같이 1.0만큼 체크되었지만, 그 이후로는 스케일된 시간 쪽은 정확히 1.0에 멈춘 채로 확인되었고 스케일되지 않은 시간 쪽은 아무 일도 생기지 않았다는 듯이 계속해서 증가하여 3초 시점에는 3.0에 도달하였습니다.

일시정지 이후 scaled 값과 unscaled 값의 진행량 변화를 비교한 꺾은선 그래프

다 안 멈추면 이상하지 않나?

여기서 자연스럽게 생길 수 있는 궁금증이 있습니다. 일시정지인데 특정 무언가는 계속해서 움직이면 오히려 어색하다고 말할 수 있지 않을까?

실제로 이 판단은 완전히 게임 개발자의 역할입니다. 게임 시간 처리에 대한 유명한 글 “Fix Your Timestep!”에서 개발자 글렌 피들러는 시간을 다루는 방식이 시뮬레이션의 결과를 좌지우지하는 민감한 문제라고 역설하며 일관되지 않은 시간 처리가 물리 시뮬레이션을 망칠 수 있다고 지적한 사실이 있습니다.

더불어 일시정지 메뉴의 커서 애니메이션이나 배경의 잔잔한 이펙트처럼 “게임의 진행과는 상관이 없는 연출”은 계속 움직이게 방치하는 것이 자연스럽지만 몬스터의 공격 이펙트와 같이 게임 진행과 직접적으로 연관이 있는 연출까지 스케일되지 않은 시간으로 바꾸게 되면 오히려 일시정지 중에 공격을 맞은 것처럼 연출되는 뒤죽박죽인 상황이 발생될 수 있습니다. 결과적으로는 어떤 것을 스케일된 시간에 묶고 어떤 것을 안 묶어둘 것인지 개발자가 하나씩 따져야 하는 판단인 것이지 자동으로 정해지는 것이 아니라고 할 수 있습니다.

핵심 정리

일시정지를 눌러도 이펙트만 계속 움직이는 까닭은 게임 속 시간이 하나가 아니라 두 개로 흐르고 있었기 때문이었습니다. 이번 실험을 통해서 두 값이 일시정지 시점까지는 동일하게 움직이다가 그 순간부터 하나는 완전히 멈추고 하나는 그대로 흘러간다는 것을 확인할 수가 있었습니다.

그 갈라지는 지점을 숫자와 그래프로 표현하여 직접 눈으로 확인하고 나니 이펙트만 안 멈추는 현상이 꽤 자연스러운 현상이라는 것을 깨닫게 되었습니다. 독자분들이 훗날 일시정지 기능을 만들어야 하는 순간이 온다면 이번 글을 꼭 참고하여서 좋은 결과 얻으시기를 바라겠습니다.

댓글 남기기