게임에서 같은 서버에 있다고 해서, 서로 같은 시간를 가지는 것은 아니다. 서버 머신에서 게임을 만들고, 클라이언트에서 서버에 접속한다면 서버 머신의 시간이 A, 클라이언트 머신의 시간이 B라면 A > B가 될 것이다.
라운드로 진행되는 게임의 경우, 서버와 동기화를 맞추지 않는다면 각 머신에서 남은 시간은 서로 다를 것이다. 그러므로 서버를 기준으로 클라이언트의 시간 동기화가 필요하다.
이는 RPC로 구현할 수 있다.
// Requests the current server time, passing in the client's time when the request was sent
UFUNCTION(Server, Reliable)
void ServerRequestServerTime(float TimeOfClientRequest);
// Reports the current server time to the client in response to ServerRequestServerTime
UFUNCTION(Client, Reliable)
void ClientReportServerTime(float TimeOfClientRequest, float TimeServerReceivedClientRequest);
void ASomePlayerController::ServerRequestServerTime_Implementation(float TimeOfClientRequest)
{
// TimeOfClientRequest : 클라이언트가 서버에 동기화 신호를 보낸 시간
// ServerTimeOfReceipt : 서버가 동기화 신호를 받은 시간
float ServerTimeOfReceipt = GetWorld()->GetTimeSeconds();
ClientReportServerTime(TimeOfClientRequest, ServerTimeOfReceipt);
}
void ASomePlayerController::ClientReportServerTime_Implementation(float TimeOfClientRequest, float TimeServerReceivedClientRequest)
{
// TimeOfClientRequest : 클라이언트가 서버에 동기화 신호를 보낸 시간
// RoundTripTime : 클라이언트가 동기화 신호를 보내고 서버에서 신호를 받을 때까지 걸린 시간
// CurrentServerTime : 현재 서버의 시간. 서버에서 클라이언트로 신호를 보낸 시간과 클라이언트에 도달하기 까지 걸린 시간을 더한 시간
// ClientServerDelta : 현재 클라이언트와 서버와의 시간차
float RoundTripTime = GetWorld()->GetTimeSeconds() - TimeOfClientRequest;
float CurrentServerTime = TimeServerReceivedClientRequest + (0.5f * RoundTripTime);
ClientServerDelta = CurrentServerTime - GetWorld()->GetTimeSeconds();
}
ServerRequestServerTime은 클라이언트에서 호출되고 서버에서 실행된다. 클라이언트가 호출한 시간과, 서버가 이 호출을 받은 시간을 파라미터로 ClientReportServerTime을 호출한다.
ClientReportServerTime은 서버에서 호출되고 클라이언트에서 실행된다. RoundTripTime은 클라이언트에서 ServerRequestServerTime을 호출하고 ClientReportServerTime을 호출받을 때까지 걸린 시간이다. CurrentServerTime은 클라이언트가 ServerRequestServerTime를 호출받은 현재 서버의 시간이다. 서버가 ServerRequestServerTime을 받은 시간과 서버가 ClientReportServerTime을 호출하고 클라이언트에서 이를 받은 시간을 더한 시간이다.
이제 서버의 현재 시간을 알았으므로, 서버의 현재 시간에 클라이언트의 현재 시간을 빼면 두 머신의 시간 차이인 ClientServerDelta를 알 수 있다.
이제 ClientServerDelta를 이용해서 클라이언트에서도 서버의 시간을 알 수 있다.
float ASomePlayerController::GetServerTime()
{
if (HasAuthority())
{
return GetWorld()->GetTimeSeconds();
}
else
{
return GetWorld()->GetTimeSeconds() + ClientServerDelta;
}
}
'Unreal Engine > 기타' 카테고리의 다른 글
[UE] AGameMode와 MatchState (1) | 2024.02.24 |
---|---|
[UE] 기본적인 멀티플레이 Game Framework (0) | 2024.01.21 |
[UE] HUD와 PlayerController (0) | 2024.01.14 |
[UE] RPC : Remote Procedure Calls (0) | 2023.12.21 |
[UE] Variable Replication (0) | 2023.12.17 |