Quick Comparison
다른 플레이어의 최신 server snapshot을 받는 즉시 표시하면 전송 간격과 jitter가 화면의 끊김으로 보입니다. 보간(interpolation)은 render time을 조금 과거로 두고, 이미 받은 두 snapshot 사이를 그립니다. 외삽(extrapolation)은 다음 snapshot이 늦을 때 마지막 속도로 잠깐 앞을 추정하는 보조 수단입니다.
| 대상·상황 | 먼저 쓸 방식 | 이유 | 위험 |
|---|---|---|---|
| 내 캐릭터의 입력 반응 | client prediction | 즉시 조작감을 제공 | server 보정 필요 |
| 다른 플레이어의 정상 이동 | interpolation | 두 확정 state 사이를 부드럽게 표시 | 일정한 표시 지연 |
| 짧은 snapshot 유실 | 짧게 제한한 extrapolation | 화면 멈춤을 완화 | 방향 전환에서 오차 확대 |
| 사망·점수·inventory event | reliable event 또는 확정 snapshot | 추정하면 규칙과 달라짐 | 늦은 event 처리 필요 |
const renderTick = latestServerTick - interpolationDelayTicks;
const [before, after] = history.findBracketing(renderTick);
const position = lerp(before.position, after.position, fraction(renderTick, before, after));보간 버퍼를 만드는 법
snapshot에는 server tick 또는 같은 기준의 simulation time이 있어야 합니다. client는 수신한 순서가 아니라 이 server 기준으로 history buffer에 넣고, latestServerTick - delay를 render target으로 잡습니다. target의 앞뒤 snapshot이 모두 있으면 position·rotation·animation state를 그 사이 비율로 보간합니다.
보간 지연은 packet jitter를 흡수하기 위한 버퍼입니다. 너무 짧으면 다음 snapshot이 도착하기 전에 render time이 따라잡아 외삽이나 멈춤이 늘고, 너무 길면 다른 플레이어가 실제보다 과거 위치에 보입니다. 고정된 하나의 숫자를 모든 연결에 강제하기보다 snapshot rate, packet loss, 게임 장르, 공정성 정책을 함께 보고 정합니다.
history에는 충분한 길이와 오래된 snapshot 제거 규칙이 필요합니다. tick이 같은 snapshot이 다시 오면 sequence·version 정책으로 하나만 남기고, 너무 늦은 snapshot이 현재 history를 거꾸로 만들지 않게 합니다. teleport, respawn, map 이동처럼 보간하면 안 되는 state는 teleport flag나 state version으로 분리해 즉시 전환합니다.
외삽은 짧고 가볍게
다음 snapshot이 늦어졌는데 화면을 마지막 위치에 멈추면 다른 플레이어가 순간 이동하는 것처럼 보입니다. 속도와 방향이 비교적 일정한 동안에는 마지막 known velocity로 잠시 앞을 계산할 수 있습니다. 그러나 방향 전환, 충돌, dash, knockback처럼 server rule에 크게 의존하는 움직임은 추정이 빠르게 틀립니다.
그래서 외삽은 최대 시간과 속도 제한을 둡니다. 제한을 넘기면 마지막 확정 위치를 유지하거나, entity를 stale 상태로 표시하고 다음 snapshot을 기다립니다. 장시간 외삽한 값을 server state처럼 취급하면 hit 판정과 AI target 선택까지 오염될 수 있습니다. 외삽은 presentation 값일 뿐 simulation 입력이 아닙니다.
snapshot에 넣을 것
모든 entity의 모든 field를 매번 전송하지 않습니다. client가 지금 보여야 하는 entity만 고르고, 이전에 확인한 state와 달라진 field를 압축하며, 해당 state가 어느 tick의 값인지 함께 보냅니다. 관심 영역은 이후 카드에서 별도 다루지만, snapshot 보간이 효과를 내려면 대상 entity의 생성·삭제·teleport event가 history 관리와 일관되어야 합니다.
내 플레이어 state도 snapshot에 들어가지만, 보통은 보간하지 않고 input acknowledgment와 함께 reconciliation에 사용합니다. local player와 remote player의 render path를 분리하지 않으면 내 입력이 늦어 보이거나 다른 플레이어가 계속 튀는 문제가 동시에 생깁니다.
interpolation delay를 0으로 낮춘다고 정확도가 올라가지는 않습니다. 두 확정 snapshot 사이를 그릴 여유가 사라지면 jitter와 유실이 그대로 화면에 나타나며, 서버 판정 시간과 화면 시간의 차이도 더 설명하기 어려워집니다.
참고 링크
2 sources