Разработка игр
Multiplayer Networking
2003 год. Counter-Strike 1.6, сервер в Москве, игрок в Новосибирске - ping 120 мс. Каждый выстрел - лотерея. Valve наняла Yahn Bernier, который написал lag compensation - систему перемотки времени прямо в игровой движок. Одно изменение превратило CS в киберспорт. Сегодня та же архитектура работает в Valorant, Apex Legends, Battlefield - с модификациями, но теми же принципами.
- **Valorant** (Riot Games) использует 128 tick servers и lag compensation до 140 мс. Систему anti-cheat Vanguard сделала возможной именно авторитарная server-side архитектура.
- **Fortnite** (Epic Games, Unreal Engine 5) использует собственный Iris Replication System - переработанный delta compression с interest management: на 100-игровом сервере трафик остаётся в пределах 2-5 KB/s на игрока.
- **StarCraft II** использует P2P lock-step с deterministic simulation на fixed-point - каждый матч 1-в-1 воспроизводим побайтово для replay и bugfinding.
Client-Server: почему сервер всегда прав
Counter-Strike 1.6 запустил революцию - не графикой, а архитектурой. Valve отказалась от peer-to-peer в пользу выделенного authoritative server: сервер хранит единственную копию игрового состояния, клиенты только отправляют входные данные и получают обновления. Это убило весь класс чит-кодов, которые модифицировали локальное состояние. Авторитетный сервер = читерство невозможно без взлома сервера. Цена: задержка. При 50 мс RTT (Round-Trip Time) игрок ждёт 50 мс между нажатием кнопки и подтверждением от сервера. Именно это сделало client-side prediction обязательной техникой - без неё управление ощущается 'через желе'.
Архитектуры мультиплеера: Lock-step (каждый тик все игроки шлют ввод, следующий кадр только после получения всех - детерминировано, но медленно), client-server с delta compression (Quake/Source Engine), relay server (WebRTC с посредником). AAA: Unreal Engine NetDriver, Unity Netcode for GameObjects, Mirror Networking.
Почему авторитарный сервер эффективен против читеров, изменяющих скорость персонажа?
P2P и Peer-to-Peer: lock-step и NAT traversal
Файтинги (Street Fighter V, Mortal Kombat 11) и RTS (StarCraft II) используют peer-to-peer с lock-step синхронизацией: каждый игрок выполняет один и тот же детерминированный симуляционный шаг с одними и теми же входными данными. Плюс - нет сервера, нет центральных издержек, идеально для 2-4 игроков. Минус - один отставший игрок тормозит всех. Главная техническая проблема P2P - NAT traversal: большинство игроков за NAT-роутером, и прямое соединение требует hole punching через STUN-сервер. WebRTC решает это готовым стеком. GGPO (Good Game Peace Out) - знаменитая P2P-библиотека для файтингов: rollback netcode, до 8 кадров prediction.
Детерминизм в P2P lock-step критичен: float arithmetic дает разные результаты на разных CPU/ОС из-за rounding modes. Решения: fixed-point арифметика (как в SC2), строгий IEEE 754 режим, детерминированные RNG с общим seed.
Почему P2P lock-step использует fixed-point арифметику вместо float?
Синхронизация состояния: snapshots и delta compression
Каждый тик сервер не может отправлять полное состояние мира - это сотни KB/s на одного игрока. Quake III Arena (1999) решил это delta compression: клиент хранит последний подтверждённый snapshot, сервер шлёт только diff. Позиция изменилась на (dx=2, dy=0) вместо (x=1026, y=512). Aligns with: Entity Component System (ECS) хранит состояние компактно, и сериализуется побитово. Bit packing: вместо float 32-бит для позиции - 16-бит fixed-point с нужной точностью. Valve Source Engine при 64 тиков/сек использует ~30-50 KB/s на игрока - это и есть результат агрессивного delta + bit packing.
Interest management: игрок в шутере видит ~50 м вокруг себя. Отправлять состояние объектов в 3 км не нужно. Spatial partitioning (octree, grid) определяет relevance set для каждого игрока - это снижает трафик в 10-100 раз в больших мирах.
Что произойдёт если клиент потеряет пакет с baseline snapshot при delta compression?
Lag Compensation: перемотка времени на сервере
Задержка 100 мс - враг всех шутеров. За 100 мс игрок переместился уже на 10 метров. Если сервер проверяет попадание по текущей позиции игрока, а клиент видел его 100 мс назад - выстрел пройдёт мимо несмотря на корректное прицеливание. Valve решила это Lag Compensation в Half-Life 2 (2004): сервер хранит ring buffer истории позиций (~1 секунда). При получении выстрела сервер 'перематывает' состояние мира на время (server_time - client_latency) и проверяет хитбокс в том положении, которое видел клиент. Звучит как обман - но это делает игру честной для стрелка. Counter-аргумент: жертва страдает - её 'убили' из прошлого. Баланс между стрелком и жертвой - дизайнерское решение.
Source Engine limitы: lag compensation работает до MAX_DELTA_TIME (0.2 сек по умолчанию). Выше этого порога компенсация не применяется - иначе высоко-латентные игроки получали бы слишком большое преимущество. Overwatch использует 120 мс как максимальный порог компенсации.
Lag compensation перематывает состояние мира назад при проверке выстрела. Кто от этого выигрывает?
Ключевые идеи
- **Авторитарный сервер** хранит единственную версию состояния; клиент шлёт только ввод. Это делает читерство на клиентской стороне бессмысленным.
- **P2P lock-step** работает для небольших игр (файтинги, RTS) с требованием детерминизма; fixed-point арифметика обязательна.
- **Delta compression + bit packing** снижает трафик в 5-10 раз; interest management - ещё в 10-100 раз для больших миров.
- **Lag compensation** перематывает историю позиций для честных хитбоксов стрелка, но создаёт trade-off против жертвы.
Связанные темы
Сетевой код строится поверх базовых сетевых и игровых систем:
- Netcode: prediction и reconciliation — Client-side prediction и server reconciliation - следующий уровень над авторитарным сервером, делающий управление плавным при любом пинге
- Entity Component System — ECS позволяет эффективно сериализовать только изменённые компоненты для delta compression
Вопросы для размышления
- Авторитарный сервер защищает от читерства, но сам сервер может быть скомпрометирован. Какие механизмы используют AAA-студии для обнаружения аномалий на сервере?
- P2P lock-step требует ввода от всех игроков каждый тик. Как масштабировать это на 4-8 игроков с разными пингами (50 мс и 300 мс)?
- Interest management отключает репликацию далёких объектов. Как поступать с объектами на границе дальности видимости, которые игрок может атаковать через scope?