Quake 3와 같은 정밀한 네트워크 게임을 위해 서버-클라이언트 시계를 동기화 상태로 유지하는 방법은 무엇입니까?


15

2D 하향식 사수를 작업 중이며 Quake 3과 같은 네트워크 게임에 사용 된 개념을 복사하기 위해 최선을 다하고 있습니다.

  • 권위있는 서버가 있습니다.
  • 서버는 클라이언트에게 스냅 샷을 보냅니다.
  • 스냅 샷에는 타임 스탬프 및 엔터티 위치가 포함됩니다.
  • 스냅 샷 위치간에 엔티티가 보간되므로 움직임이 부드럽게 보입니다.
  • 필연적으로 엔티티 보간은 "과거에"약간 발생하여 보간 할 스냅 샷이 여러 개 있습니다.

내가 직면 한 문제는 "시계 동기화"입니다.

  • 간단하게하기 위해 패킷을 서버로 전송하거나 서버에서 전송할 때 대기 시간이없는 것으로 가정 해 봅시다.
  • 서버 클럭이 클라이언트 클럭보다 60 초 앞선 경우 스냅 샷 타임 스탬프는 클라이언트 로컬 타임 스탬프보다 60000ms 앞선 것입니다.
  • 따라서, 클라이언트 스냅 샷은 클라이언트 시계가 따라 오는 데 시간이 오래 걸리기 때문에 클라이언트가 주어진 엔티티가 자신의 움직임을 확인하기 전에 약 60 초 동안 수집 및 앉아 있습니다.

스냅 샷을받을 때마다 서버와 클라이언트 시계의 차이를 계산하여이 문제를 해결했습니다.

// For simplicity, don't worry about latency for now...
client_server_clock_delta = snapshot.server_timestamp - client_timestamp;

엔티티가 보간에 얼마나 멀리 있는지 결정할 때 클라이언트의 현재 시간에 차이를 추가하기 만하면됩니다. 그러나 이것의 문제점은 스냅 샷이 다른 것보다 빠르거나 느리게 도착하기 때문에 두 시계 사이의 차이가 갑자기 변동하기 때문에 위험을 초래한다는 것입니다.

인지 할 수있는 유일한 지연이 보간을 위해 하드 코딩 된 지연과 일반적인 네트워크 대기 시간으로 인해 발생하는 지연만큼 충분히 클록을 동기화하려면 어떻게해야합니까?

다시 말해, 시계가 크게 동기화되지 않은 상태에서 보케가 발생하지 않고 보간이 너무 늦거나 너무 빨리 시작되지 않도록하려면 어떻게해야합니까?

편집 : Wikipedia 에 따르면 NTP를 사용하면 인터넷을 통해 몇 밀리 초 이내에 시계를 동기화 할 수 있습니다. 그러나 프로토콜이 복잡해 보이며 게임에서 사용하기에는 너무 과도할까요?


어떻게 복잡 합니까? 그것은 델타 얻을 수있는 전송 및 도착, 수학의 다음 비트의 타임 스탬프와 함께 요청 및 응답 각각의
래칫 괴물

@ratchetfreak : ( mine-control.com/zack/timesync/timesync.html ) 에 따르면 "안타깝게도 NTP는 매우 복잡하고 더 중요한 것은 정확한 시간 델타에 수렴하는 속도가 느리기 때문에 NTP가 네트워크에 이상적입니다. 플레이어가 게임을 즉시 시작할 것으로 예상하는 게임 플레이 ... "
Joncom

답변:


10

주변을 검색 한 후 2 대 이상의 컴퓨터의 시계를 동기화하는 것은 쉬운 일이 아닌 것 같습니다. NTP와 같은 프로토콜은 잘 작동하지만 게임에서 실용하기에는 너무 느리고 복잡합니다. 또한 UDP를 지원하지 않는 웹 소켓으로 작업하고 있기 때문에 작동하지 않는 UDP를 사용합니다.

그러나 여기서는 비교적 간단한 방법을 찾았 습니다.

클럭을 서로 150ms (또는 그 이상)로 동기화한다고 주장합니다.

그것이 내 목적에 충분할 지 모르겠지만 더 정확한 대안을 찾지 못했습니다.

제공하는 알고리즘은 다음과 같습니다.

게임에는 간단한 시계 동기화 기술이 필요합니다. 이상적으로는 다음과 같은 속성을 가져야합니다. 합리적으로 정확 (150ms 이상), 신속하게 수렴, 구현이 간단하고 TCP와 같은 스트림 기반 프로토콜에서 실행할 수 있습니다.

이러한 속성을 가진 간단한 알고리즘은 다음과 같습니다.

  1. 클라이언트는 "시간 요청"패킷에 현재 현지 시간을 표시하고 서버로 보냅니다.
  2. 서버가 서버를 수신하면 서버는 서버 시간을 표시하고 반환합니다.
  3. 클라이언트가 수신하면 클라이언트는 전송 된 시간에서 현재 시간을 빼고 대기 시간을 계산하기 위해 2로 나눕니다. 서버 시간에서 현재 시간을 빼서 클라이언트-서버 시간 델타를 결정하고 올바른 클럭 델타를 얻기 위해 반 대기 시간을 추가합니다. (지금까지이 algothim은 SNTP와 매우 유사합니다)
  4. 첫 번째 결과는 즉시 시계를 업데이트하는 데 사용되어야합니다. 로컬 시계가 최소한 올바른 야구장 (적어도 올바른 시간대)에 들어가기 때문입니다.
  5. 클라이언트는 1 ~ 3 단계를 5 번 이상 반복하여 매번 몇 초씩 일시 중지합니다. 다른 트래픽은 중간에 허용 될 수 있지만 최상의 결과를 얻으려면 최소화해야합니다
  6. 패킷 영수증의 결과는 가장 낮은 지연 시간에서 가장 높은 지연 시간 순서로 누적되고 정렬됩니다. 중간 지연 시간은이 정렬 된 목록에서 중간 점 샘플을 선택하여 결정됩니다.
  7. 중앙값으로부터 대략 1 표준 편차를 초과하는 모든 샘플은 버리고 나머지 샘플은 산술 평균을 사용하여 평균화됩니다.

이 알고리즘의 미묘한 점은 중앙값 위의 1 표준 편차를 초과하는 패킷을 버리는 것입니다. 이것의 목적은 TCP에 의해 재전송 된 패킷을 제거하는 것입니다. 이를 시각화하기 위해 TCP를 통해 5 개의 패킷 샘플이 전송되었고 재전송이 발생하지 않았다고 상상해보십시오. 이 경우 대기 시간 막대 그래프에는 중간 대기 시간을 중심으로 단일 모드 (클러스터)가 있습니다. 다른 시험에서 5 개의 단일 패킷이 재전송된다고 상상해보십시오. 재전송으로 인해이 하나의 샘플이 대기 시간 히스토그램에서 오른쪽으로, 기본 모드의 중앙값보다 평균 두 배 더 멀리 떨어집니다. 중앙값에서 하나 이상의 표준 편차에 해당하는 모든 표본을 간단히 잘라 내면 이러한 표유 모드는 대량의 통계를 구성하지 않는다고 가정하면 쉽게 제거됩니다.

이 솔루션은 시계를 동기화 한 다음 중지하여 시간이 선형으로 흐르기 때문에 내 질문에 만족스럽게 대답하는 것처럼 보입니다. 내 초기 방법은 시계를 지속적으로 업데이트했지만 스냅 샷을 수신하면 시간이 조금 뛰었습니다.


그러면 이것이 어떻게 효과가 있었습니까? 나는 지금 같은 상황에 처해있다. TCP 만 지원하는 서버 프레임 워크를 사용하고 있으므로 UDP 데이터 그램을 보내는 NTP를 사용할 수 없습니다. TCP를 통해 안정적인 시간 동기화를 요구하는 시간 동기화 알고리즘을 찾는 데 어려움을 겪고 있습니다. 그래도 1 초 안에 동기화하면 충분합니다.
dynamokaj 2012 년

@dynamokaj는 꽤 잘 작동합니다.
Joncom

멋있는. 구현을 공유 할 수 있습니까?
dynamokaj 2012 년

@dynamokaj 내가 지금 생각할 수있는 프로젝트에서 그러한 구현을 찾을 수없는 것 같습니다. 또는 나를 위해 충분히 잘 작동하는 것은 1) 하나의 핑 요청 / 응답에서 계산 한 대기 시간을 즉시 사용하고 2) 모든 미래에 이러한 응답에 대해 즉시 새로운 값을 향한 것이 아니라 점진적으로 새 값을 향하게하는 것입니다. 이것은 "평균"효과를 내 목적에 충분히 정확했습니다.
Joncom

문제 없어요. Google App Engine에서 백엔드 서비스를 실행하고 있으므로 서버가 Google NTP 서버를 사용하여 동기화되는 Google 인프라 : time.google.com ( developers.google.com/time ) 따라서 Xamarin 모바일 클라이언트에 다음 NTP 클라이언트를 사용합니다. 클라이언트와 서버 간의 오프셋을 가져옵니다. components.xamarin.com/view/rebex-time- 답변 해 주셔서 감사합니다.
dynamokaj 2012 년

1

기본적으로, 당신은 [전체] 세계를 고칠 수 없으며 결국 선을 그려야합니다.

서버와 모든 클라이언트가 동일한 프레임 속도를 공유하는 경우 연결시 (특히 대기 시간 이벤트 후) 가끔 동기화하면됩니다. 대기 시간은 시간의 흐름이나 PC의 측정 능력에 영향을 미치지 않으므로 보간이 아니라 많은 경우 외삽해야합니다. 이것은 똑같이 원치 않는 효과를 낳지 만 다시 그 효과이며, 가능한 악을 최소한으로 선택해야합니다.

많은 인기있는 MMO에서 뒤쳐지는 플레이어는 시각적으로 분명합니다. 벽에 직접 설치되어 있으면 고객이 외삽하고있는 것입니다. 고객이 새로운 데이터를 수신하면, 고객 (고객의)이 상당한 거리를 이동했을 수 있으며 "고무 밴드"또는 새로운 위치로 텔레포트 할 것입니다. 이것은 유명 브랜드 게임에서도 발생합니다.

기술적으로 이것은 게임이 아닌 플레이어의 네트워크 인프라에 문제가 있습니다. 그것이 한 지점에서 다른 지점으로가는 지점은 당신이 그리는 선입니다. 세 대의 별도 컴퓨터에있는 코드는 동일한 시간의 경과 시간을 기록해야합니다. 업데이트를받지 못하면 Update () 프레임 속도에 영향을 미치지 않아야합니다. 업데이트가 적을수록 속도가 더 빠릅니다.

"만약 당신이 인터넷에 문제가 있다면,이 게임을 경쟁적으로 플레이 할 수 없습니다."
그것은 벅이나 버그가 아닙니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.