Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Latest commit

 

History

History
48 lines (38 loc) · 4.5 KB

File metadata and controls

48 lines (38 loc) · 4.5 KB

플레이어 움직임 예측 & 재조정(Reconciliation) 시스템

개요

네트워크 환경에서 플레이어의 조작 반응성을 최적화하기 위해 예측(Prediction) 및 재조정(Reconciliation) 시스템을 설계하고 구현했습니다.

단순히 서버의 응답을 기다리는 방식이 아닌, 클라이언트에서 결과를 선제적으로 예측하고 서버의 권한을 유지하면서 오차를 보정하는 방식을 채택하여, 핑이 높은 환경에서도 이질감 없는 조작감을 제공합니다.

방식 설명 장점 단점
Stop & Wait 서버 응답 후 이동 구현 단순함, 완벽한 동기화 입력 지연 발생, 유저 경험 저하
Teleport 선 이동 후 오차 시 텔레포트 즉각적인 반응 핑이 높을 시 심한 끊김과 떨림 발생
Prediction & Reconciliation 선 이동 후 과거 시점 재현 최고의 반응성 및 부드러움 구현 복도 높음, 결정적 시뮬레이션 필요

기술적 의사결정 및 문제 해결

초기에는 엔진 내장 물리 시스템을 사용했으나, 특정 객체(플레이어)만을 과거 시점으로 되돌려 부분적 재시뮬레이션을 수행하는 데 한계가 있었습니다.
이를 해결 하기 위해 개요의 Telport방식에 선형 보간을 섞어 이용했으나 100ms 이상의 핑에서 고무줄 현상이 크게 발생하여 foothold기반 예측-재조정 움직임 시스템을 개발하게 됐습니다.

image image

[엔진의 물리엔진을 사용한 기존의 지형 시스템 | 선 기반 foothold 시스템]

1 2

[teleport 기반 | prediction-reconciliation 기반]

image

핑 1000ms 기준 teleport기반 방식은 반응이 느려지는 것을 볼 수 있습니다.(모션은 나오지만 이동을 못함)
예측 및 재조정 방식으로 바꾼 후로 해당 현상은 사라졌습니다.

상세 메커니즘

결정적 시뮬레이션

  • 서버와 클라이언트 간의 상태 불일치를 최소화하기 위해 모든 이동 로직은 FixedUpdate 기반의 고정 프레임워크에서 실행됩니다. 이는 프레임 드랍 등 클라이언트 환경 변화와 무관하게 일관된 물리 연산 결과를 보장합니다.

클라이언트

  • 상태 기록: 틱(Tick)마다 현재의 요청 번호, 위치, 속도, 입력값을 버퍼에 저장합니다.
  • 입력 감지 및 전송: 입력 상태가 변경될 경우에만 서버에 패킷을 전송하여 네트워크 대역폭을 최적화합니다.
  • 예측 수행: 서버의 응답을 기다리지 않고 로컬에서 즉시 물리 연산을 수행하여 캐릭터를 이동시킵니다.
  • 재조정: 서버로부터 상태 패킷이 도착하면, 해당 시점의 로컬 기록과 서버 데이터를 비교합니다.
    • 임계치 이상의 오차 발생 시 서버가 확정한 과거 시점으로 위치를 되돌린 후, 버퍼에 쌓인 미확인 입력값들을 순차적으로 다시 적용하여 현재 위치를 결정합니다.

서버

  • 입력 검증: 클라이언트로부터 받은 입력 패킷을 검증하고, 새 입력이 오기 전까지 마지막 입력을 유지하며 FixedUpdate에서 시뮬레이션을 진행합니다.
  • 특정 주기마다 플레이어에게 상태 패킷을 전송합니다.
    • 서버는 클라이언트의 틱 정보를 바탕으로, 해당 이동이 완료된 시점의 클라이언트 틱을 계산하여 응답에 포함합니다. 이는 클라이언트의 재조정에 사용됩니다.
      • 패킷을 보낸 시점의 클라이언트 틱 + (현재 서버 틱 - 패킷을 받은 시점의 서버 틱);

Note

클라이언트로부터 받은 입력은 즉시 처리하는 것이 아니라, 클라와 서버의 틱 차이를 계산하고 서버는 그 차이만큼 늦게 처리합니다. 그렇게 하지 않으면 아주 짧은 입력의 경우 키를 뗄 때까지 클라이언트는 3틱만큼 물리 연산을 했지만, 서버는 5틱만큼 처리하는 경우가 생겨 예측에 오차가 발생합니다.