플레이어가 멈 추면 로컬 입력 예측으로 인해 표류하는 것을 어떻게 막을 수 있습니까?


14

2D 서버 클라이언트 멀티 플레이어 게임 엔진 ( 여기서 시도해 볼 수 있음 )을 작업 중입니다. WebRTC를 사용합니다 DataChannel. 연결은 피어 투 피어이지만 호스트 피어는 여전히 서버 역할을합니다.

가장 큰 문제 (연결성 제외)는 로컬 입력 예측입니다. 우리는 평소와 같이합니다. 키를 누를 때 플레이어는 즉시 움직이고, 어떤 키를 눌렀는지 호스트에게 알리고, 호스트로부터 데이터를 다시 받아 과거의 위치와 비교합니다. 차이가 있으면 시간이 지남에 따라 위치가 수정됩니다. 이것은 핑이 높더라도 낮은 패킷 손실 또는 PDV 에서 잘 작동합니다 .

손실 또는 PDV가있는 경우 편차가 더 클 수 있습니다. 입력 변경을 나타내는 첫 번째 패킷이 지연되거나 삭제되면 호스트가 나중에 찾아서 로컬 입력 사전 표시보다 나중에 플레이어를 변경하기 시작하기 때문입니다.

플레이어가 움직이면 눈에 띄지 않기 때문에 적용된 보정량을 늘립니다. 이것은 움직일 때와 움직일 때 틈새를 덮는 것 같습니다. 그러나 갑자기 멈 추면 수정이 더 눈에.니다. 그런 다음 PDV 또는 손실이 호스트가 나중에 중지했다고 생각하면 호스트가 오버 슈트하고 데이터를 조금 더 앞당겨서 다시 보내며 수정하면 플레이어가 조금 드리프트합니다. 비정상적인 연결에서 플레이어는 종종 정지 후 눈에 띄게 표류합니다.

다른 게임에서는 이것을 눈치 채지 못했습니다. 이것을 어떻게 완화 할 수 있습니까?


3
서버가있는 P2P 게임? 여기에 문제가 있습니다.
API-Beast

죄송합니다. '서버'는 '호스트 피어'를 의미합니다.
AshleysBrain

2
서버가 피어 투 피어로 만들지 않기 때문에 플레이어 중 하나가 포즈를 취하고 있기 때문에 피어 투 피어 모델처럼 보이지 않습니다. 당신이 사용하는 기술은 확실히 클라이언트-서버 기술입니다. P2P에서는 모든 클라이언트를 완전히 신뢰하거나 (예 : 각 피어가 자신의 플레이어가있는 다른 피어에게 요청 함) 전혀 신뢰하지 않습니다 (예 : 모든 피어가 수신 할 때까지 입력 지연).
API-Beast

아 ... 그것은 실제로 좋은 점입니다 ... 혼합되었습니다 : 연결은 피어 투 피어 (WebRTC 가하는 것입니다)이지만 엔진 자체는 서버 클라이언트입니다 (피어 중 하나는 서버 일뿐입니다) ). 좋은 지적.
AshleysBrain

2
이것이 내가 생각하는 것은 YouTube의 Andrew RussellStick Ninjas dev 로그 , 특히 예측 오류 수정에 관한 로그입니다 . 표류하는 내용은 해당 비디오에서 발생하는 것과 매우 유사한 소리를 내며 Andrew는 세부 사항을 설명합니다. 이것들이 관련이 있습니까, 아니면 아마도 같은 문제입니까?
Anko

답변:


8

네트워크 계층에는 합의 된 시계가 있어야합니다. 그들은 게임 초반에 시계 값에 동의하고 드리프트의 경우 주기적으로 재 동기화 할 수 있으므로 호스트는 특정 패킷이 실제로 도착하는 데 걸린 시간과 클라이언트가 작업을 수행 한 시간 및 그 반대를 알 수 있습니다.

게임에서 시계를 동기화하는 한 가지 방법 은 이 기사 를 참조하십시오 . 다른 것도 있습니다. 구체적인 수단은 중요하지 않습니다.

문제의 후반부는 서버가 클라이언트가 입력 적용을 중단 한 시간을 지나서 입력을 적용한다는 것입니다. 마지막으로 알려진 이동 이후 서버의 이동 입력을 무시하려면 서버에서 과거 이동 버퍼와 클라이언트의 일부 논리가 필요합니다.

먼저 서버 버퍼. 서버는 플레이어로부터받은 마지막 입력의 시계 스탬프를 추적해야합니다. 또한 플레이어에게 적용되는 모든 움직임, 움직임의 시계 스탬프가 필요합니다. 입력이 수신되면 입력 패킷보다 새로운 시계 스탬프가 적용된 모든 최근 이동 이 삭제되고 모든 이동이 입력 패킷에서 다시 적용됩니다. 따라서 서버가 일부 입력을 기반으로 플레이어를 과도하게 이동하면 업데이트 된 입력이 해당 이동을 취소하고 플레이어의 새 위치는 서버가 보유한 최신 입력 정보를 기반으로합니다.

클라이언트 측에서 클라이언트는 서버에 입력을 마지막으로 보낸 시간을 알고 있습니다. 서버의 각 플레이어 업데이트에는 서버가 알고있는 마지막 입력의 시계로 태그가 지정되어 있어야하므로 클라이언트는 입력 태그가 만료 된 서버 업데이트를 무시하고 클라이언트 예측 만 고수 할 수 있습니다. 결국 새로운 서버 업데이트가 최신 입력으로 제공되며 클라이언트는이를 업데이트 할 수 있습니다.

서버는 입력 클럭의 유효성을 검사하고 부정 행위를 방지하기 위해 너무 많은 기대를 벗어나지 않도록해야합니다. 입력 클럭은 계산해야하는 반 라운드 트립 시간보다 크게 크지 않아야합니다. 합리적인 범위에있는 것은 모두 클램프하십시오 ( [Now-2*RTT,Now]예 :).

지연 시간이 길면 클라이언트는 오래된 입력을 기반으로 서버에서 업데이트를받을 수 있지만 시간이 오래되었다는 것을 알 수있는 방법이 없으므로 서버는 다른 위치에 따라 상당히 다른 위치를 보낼 수 있기 때문에 클라이언트는 다른 플레이어의 아바타에 많은 지터를 보게됩니다 수신 된 업데이트 된 입력 (및 히스토리의 일부가 삭제되고 새 입력으로 재생) 다른 플레이어가 아바타 지터를 보는이 마지막 문제는 실제로 해결할 수 없습니다. 대기 시간이 길어지고 대기 시간이 긴 게이머는 자신의 플레이어가 부드럽게 움직이더라도 다른 플레이어에 대해 많은 불안감을 느끼게됩니다. 유일한 수정은 더 나은 연결 또는 대기 시간이 적은 피어 / 서버에서 재생하는 것입니다.


1

신뢰할 수있는 UDP 메시지를 사용하여 버튼 상태 변경 및 위치 수정을위한 신뢰할 수없는 UDP 메시지를 표시했습니다. 기본적으로 다음 기사가 도움이되었습니다. https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

약 20 또는 30의 상태 저장을 위해 위치 수정 메시지 도착에 따라 일정한 시간 간격으로 플레이어 상태를 저장함으로써 움직임 예측에 대해 말합니다. 따라서 원격 플레이어는 예측 기술을 지속적으로 적용하여 지금까지 "과거"과거에 살고있는 것처럼 보입니다. 순 메시지 대기 시간을 기준으로 메시지가 호스트에서 방금 전송 된 시간과 대략 같은 객체 위치를 얻을 수 있습니다.

그런 다음 현재 "화면상의"위치를 Lerp (선형 보간) 수학을 사용하여 예측 된 위치로 부드럽게 변환 할 수 있습니다. 아이디어는 수정 패키지 사이의 시간 간격으로 값을 보간하는 것입니다. 따라서 표시된 객체가 항상 예상 위치로 움직이는 것처럼 보입니다. 보간 값의 경우 1을 "중간 메시지 대기 시간"으로 "중간 프레임 렌더링 시간"으로 나눈 값으로 이동하면 움직임이 부드럽게 보입니다.

이 시나리오에서 게임은 모든 클라이언트에서 계산하고 서버는 속도와 위치와 같은 값을 수시로 수정합니다.

이 경우 많은 도움이되는 또 하나의 기능 : 게임 로직을 최적화하여 서버와 클라이언트가 플레이어 입력을 기반으로 거의 유사한 동작을 에뮬레이션 할 수 있도록하여 지연 시간 효과를 쉽게 무시할 수 있습니다.

프로젝트에서 사용한 전체 체계를 설명 했으므로 질문에 대한 답변을 찾을 수 있기를 바랍니다.

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