이번 포스트에서는 게임 개발에서 중요한 시간 관리에 대해 알아보려고 한다. 우리가 일상에서 느끼는 연속적인 시간과 달리, 게임 내 시간은 프레임 단위로 끊어져 있어 여러 가지 특별한 문제와 기법들이 등장하는데요. FPS, Delta Time, 시간 스케일, 네트워크 동기화, 그리고 멀티스레드 시간 관리에 대해 하나씩 살펴보자.
일상에서는 시간이 부드럽게 흐르지만, 게임은 프레임 단위로 시간이 끊어져 있다. 이 때문에 다음과 같은 문제가 발생할 수 있다:
게임의 시간 개념을 제대로 이해하면 안정적이고 예측 가능한 플레이를 구현할 수 있다.
FPS는 1초 동안 화면에 몇 개의 프레임이 표시되는지를 의미한다.
예를 들어 60FPS면 1초에 60장의 정지된 화면이 순차적으로 출력되므로, 한 프레임의 시간은 약 0.016초(1/60)이다.
실시간 액션, 슈팅, 대전 게임 등에서는 FPS가 핵심 요소이다.
Unreal Engine 같은 엔진은 화면 렌더링 문제를 해결하기 위해 V-Sync(수직 동기화)와 FPS 제한 기능을 제공한다.
이러한 기능들은 Delta Time 계산에도 큰 영향을 미쳐, 안정적인 FPS 덕분에 캐릭터 움직임이나 물리 연산이 예측 가능해진다.
Delta Time은 이전 프레임과 현재 프레임 사이에 실제로 경과한 시간이다.
FPS가 변하면 매 프레임마다 Delta Time도 달라지므로, 이를 바탕으로 이동 거리나 속도를 계산하게 된다.
예시를 보자:
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector NewLocation = GetActorLocation() + (MoveDirection * Speed * DeltaTime);
SetActorLocation(NewLocation);
}
또한, Delta Time을 활용하면 프레임 간 보간(Lerp)을 통해 자연스러운 애니메이션 전환을 구현할 수 있다.
// Delta Time에 따라 선형 보간(Lerp) 적용
FVector NewLocation = FMath::Lerp(CurrentLocation, TargetLocation, DeltaTime * InterpolationSpeed);
SetActorLocation(NewLocation);
이렇게 FPS 변화에 상관없이 초당 일정한 이동 거리를 구현할 수 있다.
게임은 프레임 단위로 시간이 끊어지기 때문에 FPS가 불안정하면 Delta Time 값이 크게 변동할 수 있다. 이를 보완하기 위한 기법들은 다음과 같다.
float DeltaTime = GetDeltaTime(); // 실제 계산된 Delta Time
const float MaxDeltaTime = 0.05f; // 예: 50ms
if (DeltaTime > MaxDeltaTime)
DeltaTime = MaxDeltaTime;시간 스케일은 게임 내 전체 시간의 흐름 속도를 조절하는 메커니즘이다.
이를 통해 게임 내 시간을 느리게, 빠르게 또는 일시 정지 상태로 만들 수 있다.
void AMyPhysicsActor::Tick(float DeltaTime)
{
// GlobalTimeScale은 전역 또는 액터 단위로 관리되는 시간 스케일 값이다.
float AdjustedDeltaTime = DeltaTime * GlobalTimeScale;
UpdatePhysics(AdjustedDeltaTime);
}
이처럼 시간 스케일을 활용하면 게임 내 다양한 효과를 손쉽게 구현할 수 있다.
네트워크 게임에서는 클라이언트 간 지연이나 패킷 손실로 인해 각 클라이언트의 로컬 시간이 조금씩 달라질 수 있다.
이를 방지하기 위해 서버와 클라이언트 간의 시간 동기화가 필수적이다.
이러한 동기화 기법은 반응 속도가 중요한 게임에서 매우 중요하다.
현대 게임은 물리 연산, AI, 렌더링 등 여러 작업을 멀티스레드로 처리한다.
이때 모든 스레드가 동일한 글로벌 타이밍 시스템을 공유해야 전체 게임 로직이 일관되게 업데이트된다.
FPlatformTime::Seconds() 등의 함수를 이용해 정확한 시간 측정 후 Delta Time을 계산한다.예시 코드:
// FRunnable 기반 스레드 내에서의 시간 관리 예시
double GlobalTime = FPlatformTime::Seconds();
float DeltaTime = GlobalTime - LastUpdateTime;
LastUpdateTime = GlobalTime;
// 이 Delta Time을 이용해 물리 연산을 업데이트한다.
UpdatePhysics(DeltaTime);
게임 개발에서 시간 관리는 안정적이고 예측 가능한 게임 플레이를 위해 매우 중요한 요소이다.
FPS 안정성, Delta Time의 일관성, 시간 스케일 조절, 네트워크 동기화, 그리고 멀티스레드 시간 관리 등 다양한 기법들을 적절히 활용하면, 플레이어에게 일관된 경험을 제공할 수 있다.