말감로그

네트워크 동기화 본문

Unity

네트워크 동기화

habbn 2025. 2. 22. 03:22
728x90

네트워크 동기화를 위해 필요한 정보

 

1. 위치와 회전

-> 캐릭터의 정확한 상태를 서버와 다른 클라이언트에게 전달하기 위해

- 클라이언트 A가 움직이면 , 클라이언트 B에게도 동일한 위치로 보여야 함.

  • 클라이언트 A → 서버: "내 위치는 (10, 5), 회전은 90도야!"
  • 서버 → 클라이언트 B: "클라이언트 A의 위치는 (10, 5), 회전은 90도야!"
  • 클라이언트 B는 이를 받아 화면에 반영함.

2. 속도와 가속도

-> 예측 보정과 부드러운 동기화를 위해

- 네트워크에서는 패킷이 항상 즉시 도착하지 않음 (네트워크 지연, 패킷 손실 등)

- 속도와 가속도를 보내면 서버와 클라이언트가 패킷이 도착하기 전에 캐릭터의 움직임을 예측(보간,외삽)할 수 있음

  • 클라이언트 A → 서버: "내 속도는 (2, 0)이고, 가속도는 (1, 0)이야!"
  • 서버는 50ms 후 새로운 위치를 계산: 새 위치 = 현재 위치 + (속도 * 시간) + ½ * (가속도 * 시간²)
  • 서버가 위치를 업데이트하여 다른 클라이언트에게 전송함.
  • 네트워크 지연이 있어도, 클라이언트들은 속도와 가속도를 이용해 부드럽게 움직임을 보간할 수 있음

- 속도 가속도가 없으면 네트워크 지연이 생길 때마다 캐릭터가 순간이동하듯 움직일 수도 있음

 

3. 타임스탬프 (해당 패킷이 생성된 정확한 시간)

-> 네트워크 지연 보정과 패킷 정렬을 위해

- 네트워크에서는 패킷이 순서대로 오지 않을 수도 있음

- 타임 스탬프가 있으면, 서버는 패킷이 언제 생성되었는지 확인하고 올바른 순서로 정렬할 수 있고, 패킷이 도착하는 데 걸린 시간을 고려하여 클라이언트의 움직임을 보정할 수 있음.

  • 클라이언트 A → 서버: "10:00:00.200에 내 위치는 (5,5)였어!"
  • 서버는 클라이언트 A의 패킷이 지연되었음을 인식하고, 보간(Interpolation)으로 현재 위치를 보정할 수 있음.
  • 클라이언트 B에게 보낼 때 시간 차이를 보정하여 더욱 정확한 동기화가 가능함.

* 가속도를 포함한 경우, 위치가 튕기는 현상 

-> 가속도는 시간이 지날수록 속도를 계속 변화시키기 때문에, 네트워크 지연이나 패킷 손실이 있을 경우 예측이 부정확해질 가능성이 커짐.

만약 패킷이 80ms 동안 지연되었다고 할 때

 

- 속도만 있다면 : 새로운 위치 = 현재 위치 + (속도 * 시간)

 

- 가속도가 있다면 : 새로운 위치 = 현재 위치 + (속도 * 시간) + ½ * (가속도 * 시간²)

 

-> 가속도가 포함된 경우, 시간의 제곱이 반영되기 때문에, 네트워크 지연이 발생하면 위치 차이가 더 커질 수 있음

 

즉, 클라이언트에서 예측한 위치와 서버에서 계산한 위치가 크게 차이나면, 클라이언트는 갑자기 차량이 튀는 것처럼 보이게 됨

그래서 가속도를 빼고 속도만 사용하여 위치를 예측하면 네트워크 지연이 발생해도 위치 보정이 더 간단해지고 안정적이게 된다.


네트워크 동기화에서는 패킷이 일정한 간격으로 오지 않을 수 있기 때문에 플레이어의 위치를 자연스럽게 이어주기 위해 보간과 외삽을 사용

 

1. 보간(Interpolation) - 사이 값을 자연스럽게 이어주는 것

두 개 이상의 값 사이의 중간 값을 계산하는 방법

즉, 과거 데이터와 현재 데이터가 있을 때, 그 사이 값을 예측해서 부드럽게 연결하는 방식

 

2. 외삽(Extrapolation) - 데이터를 예측해서 미리 보낸다.

현재 값과 속도를 이용해 미래 값을 예측하는 방법.

즉, 현재 위치와 속도를 기반으로, 앞으로 갈 위치를 예상해서 미리 이동하는 방식

 

- 위치가 상대적으로 예측하기 쉽기 때문에 외삽을 사용

서버로부터 받아온 현재 위치와 속도를 기반으로 예상 위치를 계산.

Vector3 extrapolatedPosition = toPosition + (toVelocity * Mathf.Clamp01(latency) * extrapolationWeight);
sphere.transform.position = Vector3.Slerp(fromPosition, extrapolatedPosition, lerpAmount);

 

- 회전은 연속적으로 부드럽게 변화해야 하기 때문에 물리적으로 예측하기 어려운 요소라 보간을 사용

쿼터니언을 사용하여 두 회전 사이를 자연스럽게 보

sled.transform.rotation = Quaternion.Slerp(sled.transform.rotation, toRotation, lerpAmount);

 

 

 

 

728x90