C.W.K.
Stream
Lesson 06 of 08 · published

Multiplayer Game State

~13 min · app, games, prediction

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

Input 한 rate, state 다른 rate

Multiplayer 게임이 rate 분리: 클라가 input 을 고빈도 (renderer 매칭하려 30-60Hz) 로 보냄; 서버가 권위적 state 를 저빈도 (10-20Hz) + 게임-바꾸는 action (kill, score, level 변경) 의 event message 로 보냄. 클라가 서버 snapshot 사이 interpolate 해서 60fps 에 movement smooth, state 가 15Hz 로 도착해도.

Client-side prediction

Latency 가 'input 보내고 server state 기다림' 을 끔찍하게 만듦 (모든 keypress 마다 100ms+ 지연). 답은 client-side prediction: input 을 로컬에 즉시 적용 후 서버 권위 state 도착 시 reconcile. 서버 disagree 하면 snap 또는 smoothly 보정. Quake III 가 만든 패턴; 모든 modern multiplayer 가 어떤 form 으로 사용.

Code

클라: input loop + prediction + reconcile·javascript
const INPUT_RATE = 1000 / 30; // 30 Hz
let seq = 0;
const pendingInputs = [];

setInterval(() => {
  if (ws.readyState !== WebSocket.OPEN) return;
  const input = {
    seq: seq++,
    keys: getPressedKeys(),
    mouse: getMousePosition(),
    ts: performance.now(),
  };
  // 1. Send to server.
  ws.send(JSON.stringify({ type: 'game.input', data: input }));
  // 2. Apply locally for instant feedback.
  applyInputLocal(input);
  // 3. Remember it for reconciliation.
  pendingInputs.push(input);
}, INPUT_RATE);

ws.on('game.state', (state) => {
  // Server says authoritative position is X for input seq N.
  // Drop everything we already reconciled.
  while (pendingInputs.length && pendingInputs[0].seq <= state.lastInputSeq) {
    pendingInputs.shift();
  }
  // Re-apply any inputs the server hasn't seen yet.
  let pos = state.position;
  for (const i of pendingInputs) pos = predict(pos, i);
  setPosition(pos);
});
서버: 저속 snapshot·python
async def state_broadcaster(manager, world):
    while True:
        snapshot = world.snapshot()  # current authoritative state
        for room in list(manager.rooms):
            await manager.broadcast(room, {
                'type': 'game.state',
                'data': snapshot,
            })
        await asyncio.sleep(1 / 15)  # 15 Hz

External links

Exercise

두 player 의 'arrow key 로 걸어다니는' 2D 데모 짜. 30Hz input, 15Hz state broadcast, reconciliation 가진 client-side prediction. 브라우저에 100ms 인공 latency 추가; movement 가 로컬에 즉시 같아야 함. Prediction 끄고 input lag 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.