Сетевые Шутеры: Как они работают

Когда ты тратишь кучу времени на что-то такое же бесполезное как сетевые шутеры, то нужно хотя бы представлять себе как они работают. Возможно это знание когда-то пригодится.
Среди одних из самых популярных шутеров выделяется Battlefield 3 вышедший пару месяцев назад. И что самое приятное, разработчики не скрывают то как идет процесс разработки. В отличие от Activision с их секретными дивизионами разработчиков клонов CoD.

Как же работает сетевая составляющая Battlefield и в частности третья часть серии? Особенно это интересно потому, что игра заметно отличается от других: тут у каждой пули есть собственная скорость на которую влияет гравитация. Хотя концепция траекторий далеко не нова, лишь немногие разработчики успешно применяют ее в сетевых шутерах, так как появляется заклятый враг всех онлайновых проектов – лаги.

Чертова Физика

Первая проблема в том, что существует скорость передачи информации. Теоретически, лимитом является скорость света, но практически это не так как – мы используем различные типы материалов для передачи информации. От радио-волн до меди и оптических материалов. Все это определенным образом влияет на скорость. А поверх всего этого есть еще и сетевое оборудование, которое снова добавляет столь драгоценные миллисекунды.
Есть три возможных решения:
1) играть только в локальной области, где из-за расстояния пинг естественно очень небольшой.
2) забить на проблему и пусть игроки сами компенсируют лаги, подстраиваясь под игру
3) использовать хитрые уловки для компенсации задержки

Хотя задержки в сети с каждым годом все уменьшаются, мы уже вплотную приблизились к физическим лимитам передачи данных, но проблема никуда не пропала.

Так что сейчас игры идут по третьему пути, обманывая игроков, заставляя поверить, что лагов нет. В большинстве игр вы не заметите эффекта от задержки в 150 мс в основном геймплее. Однако проблему видно при более высоком пинге, так как общая производительность заметно обвалится, но чаще всего в таких случаях игроки винят свое железо.

Основа

Современный сетевой шутер состоит из двух элементов. Хоста и клиента. Хост симулирует игру при определенном темпе (к примеру 20 тиков в секунду) и информирует клиентскую часть об изменениях на сервере посылая апдейты игрового мира при определенной частоте обновления. Клиент получает информацию и изображает ее на экране.

Если сервер обновляется 20 раз в секунду, то можно предположить, что вы залочены на 20Гц. Но так как вам необходима большая частота кадров, клиент применяет интерполяцию. Предполагая, что сервер тикает со скоростью 20Гц и при каждом тике на сервере клиент посылает данные, то будет необходимо визуализировать три кадра на каждый пакет данных. Суть интерполяции в том, что она может генерировать информацию только между двумя точками. Так что беря в расчет 60Гц, мы получаем около 16мс на кадр, что значит при интерполяции между одним тиком сервера, вы получите дополнительно 48мс для работы интерполяции.

Как альтернатива, теоретически можно экстраполировать данные известной точки в будущее, но это гораздо более комплексная вещь чем простая линейная интерполяция.

Что мы имеем – это основу для симуляции движений других игроков. Но что насчет локального игрока? Если локальный игрок двинется, то посылая движение на сервер и получая обратно данные для визуализации, мы получим двойной лаг, который заметно отобразится на ощущениях геймплея. Решение – использовать прогнозирование клиентской части. В компьютерных играх термин Счисление (Dead Reckoning) часто используется для объяснения концепции. В статическом мире, где ничто кроме игроков не меняется, клиент должен игнорировать движения сервера и просто симулировать те моменты когда задействованы клавиши.

В случае когда симуляция клиента и сервера отличается, мы получаем артефакты, вроде телепортации игрока. Как же это происходит? Обычно это бывает когда игрок врезается во что-то на сервере, при этом не спрогнозированное на клиентской части. К примеру, когда мы натыкаемся на других игроков или когда стоим на технике под контролем другого игрока.

Машина Времени

Фундаментальные элементы описанные выше работают неплохо для игр вроде Quake или Counter-Strike где динамическими объектами мира являются лишь игроки и ракеты. Если клиент сделает некорректный прогноз, сервер пошлет обновление позиции игрока, и если локальная машина увидит, что локальные данные и серверные отличаются, то он произведет исправление.

Однако так как данные от сервера имеют прошедшее происхождение с точки зрения симуляции данного момента, игра должна вести запись прошлого. Обычно это несколько последних сообщений сервера хранящиеся в локальном буфере, находит тот который отвечает за обновление сервера и производит симуляцию поверх исправленного состояния.

Я попал во что-то?

На этом с движениями разобрались, но что же со стрельбой? В Quake движения неплохо компенсировались через прогнозирование, но даже при этом, игроку бы пришлось предполагать будущее местоположение игрока чтобы компенсируя задержку попасть во врага. Если задержка в шутере на 100мс, при этом следить за игроком передвигающимся на 100 единиц в секунду, то стрелять нужно на расстоянии в 10 единиц от нынешнего положения врага. Согласитесь, это гемор.

Если вы играете в современные шутеры, то в них этой проблемы нет. Так как же они работают? В целом, так же. Для определения того, было ли что-то задето, клиент передает цель прямо на сервер и объявляет, что совершает стрельбу. Сервер смотрит на временные различия, перемещается в прошлое на пару шагов назад и смотрит – был ли кто-то задет в этом месте. Если был задет, то противнику начисляется урон.

Это имеет две проблемы: первая – такой метод работает только на оружии с бесконечной скоростью, так как нет реального представления пуль в пространстве и времени. Вторая – если у стрелка задержка в 200мс, то тот, кого он подстрелили в настоящем клиенте, мог уже быть за укрытием. Но так как выстрел происходит в настоящем стрелявшего, и в прошлом цели, то последний погибает из-за позиционирования серверной части.

Избавится от лагов не возможно, можно лишь создать иллюзию шуетра без лагов. Иллюзию игры в одно и то же время... которая разрушается когда вы внезапно погибаете будучи вне досягаемости вражеских пуль. Время от времени такое бывает и в Battlefield 3 на хардкоре.

Реальные Пули

Первая проблема Battlefielfd в том, что он создает пули. В Quake и других играх по карте носится около 16 игроков. Каждый раз пытаясь увидеть то, убили ли вы кого-то, сервер путешествует в прошлое позиций всех игроков и проводит вычисление по урону. А если вы используете скоростную пушку в надежде превратить все в швейцарский сыр, то дырок будет гораздо меньше, так как пули упаковываются в пакеты по несколько штук и отправляются на сервер.

В Battlefield игра создает настоящие пули со временем жизни в 1.5 секунд. Для снайперских винтовок время жизни пуль увеличено до 5 секунд. Учитывая то, что винтовки – это основное оружие в игре, то при скорострельности 700п/с основная масса пуль уходили в воздух. Что самое плохое в этом – в игре столь большие карты, что многие пули летят до своего максимального срока жизни. А теперь посчитаем сколько получится снарядов при 64 игроках + техника.

В итоге мы получаем тонны динамических объектов, эффект от которых тоже нужно симулировать. А при каждом просчете проверки на попадание, игра перемещает всех игроков назад во времени согласно личному времени пуль записанному с определенной частотой определенного игрока. Это необходимо производить с каждым шагом симуляции, а не только когда кто-то стреляет.

Разрушение и Техника

Еще одна большая проблема Battlefield – это то, что тут есть разрушаемость окружающей среды. Здания и техника – потенциальные получатели урона, и если каждый раз совершать путешествие во времени для проверки попаданий пуль, вам необходимо откатывать не только игроков во времени, это же необходимо производить для всей техники и конструкций на поле боя. Хотя в плане разрушения не обязательно проводить полную симуляцию, так как от этого не появляются новые препятствия для пуль. В конце концов тонкий слой щебня можно прострелить, а во время разрушения поднимается большая туча пыли, через которую можно стрелять без расчета ежесекундного положения обломков.

Однако в Battlefield 3 есть особенность – изменение ландшафта. Вы можете пробивать ямы в земле, и при их просчете можно столкнуться с серьезными проблемами в прогнозах и итнерполяции. Как раз по этой причине во время бета-тестирования игроки падали под землю. Это стало одной из причин, почему изменение ландшафта заметно ослабили в финальной версии.

Масштаб Данных

Имея 64 игрока на поле боя, несколько видов техники, тонны разрушений, ракеты, пули, оружие валяющееся на земле и еще черт знает что... получается долбанная куча данных для передачи. Если обратить внимание на количество трафика потребляемого Battlefield 3, то вы удивитесь – игра передает и получает не так уж много информации. Можно предположить, что разработчики пошли по пути сетевой модели Halo, которая в свою очередь была основана на модели Tribes 1. Улучшение Halo в том, что появилось несколько степеней приоритета для всех объектов. Например объекты находящиеся далеко от игрока, будут обновляться гораздо реже, чем близлежащие.

Каждую секунду на карте с 64-ю игроками сервер передает не более 20KB/с в обе стороны. Это не много.

Трюк Halo

На поле боя всегда находится очень много объектов с физикой, однако далеко не все они имеют сетевое значение. К примеру, рэг-долл модели в основном имеют связь только для инициации физического состояния, и если оно синхронизировано, то передачу данных можно игнорировать. Если заметили, то через мертвые тела солдат можно стрелять, а это самое главное. Но есть второстепенная проблема – игроки могут оживлять своих товарищей по оружию.

Если вы достаточно опытный медик, то знаете, что место респавна при оживлении контролируете именно вы. При использовании дефибриллятора, ваш товарищ оживет не точно там где находится его тело, а относительно вашего положения. Все это связано с тем, что при гибели, вы видите мир только со стороны своей клиентской части. Однако у другого игрока рэг-долл физика могла сработать иным образом, и ваше местоположение на его клиенте отличается. Это и вызывает телепортацию к тому месту, где по мнению сервера вы должны находится.

Все это не подтвержденные данные, а лишь вывод на основе наблюдений. Но не смотря на то, фиксирует ли рэг-долл физику серверная часть, любопытно наблюдать за тем, как игровой дизайн влияет на сетевую сторону геймплея. И наоборот. 

Обнаружение попаданий в Battlefield 3

У нас уже есть реальные пули с местоположением и компенсациями лагов. Но что бывает при попадании пули в цель?

В BF3 интересно то, что расчетом попаданий занимается не сервер, а клиентская часть игры. Учитывая сложность и множество характеристик оружия в Battlefield 3, это наиболее рациональный подход. Это быстро, имеет практический идеальный пиксельный просчет попадания, автоматическая компенсация лагов не съедает ресурсов. Однако это часто является причиной читерства.

Согласно Алану Кертцу, DICE для проверки на читерство проводит базовую проверку вероятности попадания. Эта функция была введена на последних стадиях бета-тестирования, когда практически полностью пропали ролики с убийствами через всю карту. Именно сервер выдает информацию о возможном читерстве, в частности при использовании бота для прицеливания. Для этого создается конусообразная модель вероятности попадания. Поэтому если все пули попадают на определенном расстоянии друг от друга, что идет в разрез гравитации и отдаче, то игрок соответственно использует чит. Хотя это не гарантирует 100%-й успех, решение близко к идеалу.

Собственная сетевая игра.

Что же вам нужно знать чтобы написать свою сетевую игру? В сети есть несколько неплохих вещей, в основном они на английском.

  • Статьи Гленна Фидлера по игровой разработке: Networking for Game Programmers и Networked Game Physics. Начинать лучше всего с этого.
  • На сайте Gamasutra есть статья 1997-го года о Счислении (Dead Reckoning), неплохо для введения в тематику.
  • Обзор кода Quake от Фабиена Сангларда. Объясняет сети и прогнозирование. В целом движок Quake – так же неплохая точка для начала.
  • Wiki разработчиков Valve шикарный источник информации. У них есть материалы о компенсации лагов, прогнозировании, и интерполяции, а так же материал Яхна Бэрнира на тему сетевых движков.
  • Разговор на GDC о Halo – I shot you first
  • GDC 2008 в Остине – Robust Efficient Networking от Бена Гэрни. 

P.S. По сравнению с этим, Modern Warfare 3 ушел не так уж далеко от Unreal Tournament.

By Armin Ronacher

Больше статей на Shazoo
Тэги: