Компенсация отставания в сетевых 2D играх

31

Я хочу сделать 2D-игру, которая по сути является физически управляемой песочницей / игрой-деятельностью. Есть кое-что, чего я действительно не понимаю. Судя по результатам исследований, обновления с сервера должны происходить примерно каждые 100 мс. Я могу видеть, как это работает для игрока, поскольку он может одновременно симулировать физику и выполнять компенсацию запаздывания посредством интерполяции.

Я не понимаю, как это работает для обновлений от других игроков. Если клиенты получают уведомления о позициях игроков только каждые 100 мс, я не вижу, как это работает, потому что многое может произойти за 100 мс. Игрок мог изменить направление дважды или около того за это время. Мне было интересно, если кто-нибудь будет иметь некоторое понимание этого вопроса.

В основном, как это работает для стрельбы и тому подобного?

Благодарность

jmasterx
источник

Ответы:

58

Резюме для тех, кто не любит длинные ответы ...

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


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

Проблема в том, что физика должна быть быстрой и отзывчивой, чтобы быть реалистичной, но в то же время она должна рассчитываться на основе комбинированных действий ВСЕХ факторов, то есть комбинированных действий всех игроков. И если есть задержка, это не может быть сделано в режиме реального времени.

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

Пример, чтобы показать, как все может запутаться

Представьте себе игру, в которой два игрока (клиенты) подключены к серверу. Для передачи сообщения через Интернет от клиента к серверу требуется 100 миллисекунд (1/10 секунды). Когда игрок что-то делает, на сервер отправляется сообщение о том, что он сделал. Затем сервер передает сообщение другим игрокам, чтобы они все знали, что сделал действующий игрок.

Теперь создайте сценарий, в котором два игрока имеют ящик на земле, который является физическим объектом. Игрок A ударяет его по одной стороне, отправляя его в каком-то направлении. Однако в то же время игрок B ударяет по нему с другой стороны, отправляя в другом направлении.

Давайте посмотрим на различные способы справиться с этим и каковы будут результаты ...

Что если физика рассчитывается только на сервере?

Предположим, у нас есть физика, рассчитанная только на сервере. Игрок А отправляет на сервер сообщение «Я попал в ящик таким образом», а спустя 1/10 секунды сервер получает сообщение. Игрок Б отправляет сообщение «Я попал в ящик другим способом». Сервер вычисляет изменение физики на основе комбинации двух действий и отправляет сообщение обоим игрокам, говоря: «Хорошо, он движется так». Совершенная физика выполняется, основываясь на действиях обоих игроков вместе взятых.

Но проблема в том, что пройдет 2/10 секунды, прежде чем любой из игроков увидит, как сундук среагирует. Сообщения от обоих игроков занимают 1/10-ю секунды, чтобы добраться до сервера, затем еще 1/10-ю секунды для результатов расчета сервера, которые будут отправлены обоим игрокам.

Итог, затянувшийся геймплей.

Что, если физика просто рассчитана на клиента?

Предположим, у нас есть физика, рассчитанная только на клиента. Давайте посмотрим на это с точки зрения игрока А. Игрок А попадает в ящик, и он сразу же начинает идти в их направлении. На сервер также отправляется сообщение о том, что сделал Игрок А.

В то же время, однако, B сделал свой удар и увидел, что ящик движется в их направлении, и отправил на сервер сообщение о том, что они сделали.

2/10-й секунды спустя, сообщение приходит от сервера к клиентам. А говорят, что сделал Б, а Б говорят, что сделали. Проблема в том, что оба клиента говорят: «Хорошо, игрок X, возможно, сделал этот удар в этом месте, но в этом месте больше нет ящика, поэтому его удар ничего не сделал».

Суть в том, что две игры не синхронизированы и игроки не имеют общего опыта. Какой смысл в мультиплеере, если они оба видят разные вещи?

Что если физика рассчитана как на клиенте, так и на сервере?

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

Оба игрока попадают в ящик в соответствующих направлениях, и каждый видит движение корзины, основываясь только на своем ударе. Но затем, спустя 2/10 секунды, сервер возвращается и говорит: «На самом деле, вы оба не правы. Ящик пошел по этому пути». Внезапно оба игрока видят, как ящик резко меняет направление и бросается в новое место.

Итог, глючная игра.

Вывод

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

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

Используйте простые объемы столкновений. Не пытайтесь моделировать каждую деталь фигуры с помощью физики, когда подойдет простая фигура куба. Spikey Ball не должен быть смоделирован как spikey ball для физики. Вместо этого просто смоделируйте это как сферу.

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

Делайте объекты физическими объектами только в том случае, если они должны быть физическими объектами, чтобы число активных физических объектов было небольшим.

Запускайте игру в замедленном режиме, когда выполняете многопользовательскую физику Подумайте «время пули», может быть. Игры в замедленном темпе компенсируют задержку и позволяют нескольким игрокам взаимодействовать с физикой вместе.

Разрешить игрокам устанавливать ситуации в некотором роде вместе, а затем по некоторой подсказке симуляция физики для обоих игроков, и оба следят за результатом их объединенных действий. Игроки не могут вмешиваться в последовательность, пока она не будет завершена.

Разделяйте игроков физикой, чтобы они не могли мешать друг другу. Это было бы здорово для такой игры, как боулинг или пул, где только один игрок одновременно имеет контроль, или у каждого игрока есть своя «песочница» (например, дорожка для боулинга).

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

Приложение: Как стрелялки справляются с этим

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

Представьте себе сценарий, когда игрок A стреляет в игрока B. Ваша типичная стрелялка будет делать что-то вроде этого ...

  1. A будет локально подсчитывать, попали ли они в B, и если похоже, что есть попадание, он играет эффект «удара», как кровь. Это делается на стороне клиента, чтобы игрок сразу увидел реакцию на свои действия. Если вы этого не сделаете, игра будет тормозить.
  2. А также отправляет на сервер сообщение «Я стрелял по этому вектору»
  3. Когда сервер получает сообщение, он смотрит на то, где IT думает, что игроки находятся, и решает, ударил ли вектор броска A B.
  4. Если сервер решает, что А попадет в В, он решит, что В ударил, и отправит ОБА клиентам, что произойдет.
  5. Если сервер решает, что A НЕ ударил B, B в порядке, и A "отсутствует". Может показаться, что они попали («Я видел кровь!»), Но пропустили вызов серверов.

Так как же А мог пропустить Б, когда казалось, что они их бьют? Поскольку B, возможно, переехал, но A еще не видел его, потому что сервер еще не отправил клиенту сообщение "B двинуто сюда".

У Valve есть хорошая рецензия на их сайт по этому поводу. См. Http://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

Тим Холт
источник
2
Это верно для сервера с хорошим соединением. Есть много случаев, когда физика в многопользовательских играх терпит неудачу, и я уверен, что в играх Garry's Mod есть много плохого опыта физики. Однако, если есть задержка, проблемы, которые я изложил, будут существовать. Вы не можете обойти тот факт, что физика должна быть рассчитана очень быстро, чтобы быть гладкой. И если у вас будет задержка, будет задержка. Задержка означает отставание.
Тим Холт
1
Возможно, вы захотите вернуться и перечитать мой пост. За исключением некоторых высказываний с моей стороны, я точно описываю, что происходит в симуляторе физики с несколькими игроками, включая сеансы игры Garry's Mod. Вы не можете обойти факты.
Тим Холт
2
Хорошо, я изменил свое понижательное голосование в положительное. Но вы рисуете действительно негативную картину для многопользовательских игр с физикой, когда это действительно было сделано раньше и относительно без проблем.
AttackingHobo
7
@AttackingHobo: «Без сбоев» является относительным. Поработав над игрой с хорошим предсказанием сети, я теперь вижу глюки, которых раньше не было. Они редко оказывают существенное влияние на механику, но они присутствуют. Весь смысл прогноза в том, что небольшая погрешность в реальном времени лучше, чем задержанная точность; это не меняет того факта, что вы всегда неточны.
1
+1 за «Вообразите историю о том, чтобы быть в глючной вселенной с нарушенными законами физики или чем-то подобным».
Патрик Чачурски
13

Я написал серию статей на эту тему здесь: http://www.gabrielgambetta.com/fpm1.html

Первые три статьи посвящены введению в тему, предсказанию на стороне клиента, согласованию сервера и интерполяции сущностей (эта часть отвечает на ваш конкретный вопрос). Четвертая статья (скоро) будет посвящена «стрельбе» :)

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

ggambett
источник
Хорошие вещи, ggambett!
Тим Холт
2
Так много игроков не понимают, как это работает, но так важно понимать вечное: «ЧЕГО ПОЧЕМУ Я ПРОПУСТИЛ?» вопрос.
Тим Холт
Или «почему мой персонаж привязан к этой колонне гигантской резинкой?» на сброшенном соединении :)
ggambett
В Wiki от Valve есть рецензия, в которой также рассматриваются эти вопросы. Страница находится по адресу developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
Тим Холт,
1
Я люблю Live Demo. Какой отличный способ визуализировать то, что происходит.
Ричард Марскелл - Дракир
2

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

Kylotan
источник
0

В конце концов, все дело в том, чтобы справиться с доступными сетевыми ресурсами. В идеале мы бы жили в мире с нулевой задержкой, и все было бы идеально синхронизировано. Реально, вы обновляете клиентов каждые 100, 200, 300 мс, и в клиенте должна быть логика, чтобы происходящее выглядело гладко. «Гладкость» очень важна, в конце концов, игра просто должна чувствовать себя гладкой, даже если на заднем плане происходит какая-то хаотическая синхронизация между клиентом и сервером.

Хороший пост и лучший ответ можно найти:

Как написать сетевую игру?

DeusAduro
источник
0

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


источник