Как часто обновляется игровой клиент о мире?

10

Используя socket.io , у меня есть связь, аналогичная другим MMORPG, постоянная связь с сообщениями.

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

Будет ли лучшей идеей «собирать» их и транслировать, скажем, раз в 1/10 секунды?

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

Lanbo
источник

Ответы:

16

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

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

Как разработчики MMORPG, мы планируем большой успех (часто также известный как катастрофический успех), когда большое количество людей запускает сигнальные огни и сирены. Одно из самых страшных больших чисел в алгоритмах, которые имеют N-квадрат (N ^ 2 в дальнейшем), в вашем вопросе первое, что бросилось мне в глаза, это то, что это звучало так, как будто проект призывал сущность передавать информацию все остальные связанные объекты. Это классический пример задачи N ^ 2.

ММО обычно подходят к решению проблем N ^ 2, атакуя проблему несколькими различными способами; системы осведомленности (ситуативные, пространственные и т. д.), в которых объект знает о некотором подмножестве всех других объектов, разделяя игроков на разные «осколки», разделяя игроков на «зоны» и / или создавая экземпляры, реализуя игровую механику, которая препятствует слишком большому игроки, собравшиеся вместе (штормы телепортации Ашерона Колла) и т. д.

Большинство MMORPG и многие FPS-движки имеют достаточно сложные сетевые архитектуры, которые поддерживают множество функций, включая:

  • надежные и ненадежные каналы связи (TCP, пользовательские реализации надежных пакетов UDP и UDP)
  • формирование полосы пропускания (расстановка приоритетов, время жизни и т. д.)
  • автоматическая репликация полевых / доступных данных и вызовов функций
  • атомарные наборы данных (т.е. данные, которые передаются вместе)
  • дискретные обновления (т.е. где важен каждый переход)
  • коррекция латентности
  • различные приемы, чтобы клиент чувствовал себя отзывчивым

Я считаю , что документация Unreal Networking и Valve Networking документации обеспечивают хорошую грунтовку по целому ряду вопросов.

Итак, теперь давайте подойдем к вопросам.

Будет ли лучшей идеей «собирать» их и транслировать, скажем, раз в 1/10 секунды?

Здесь сложно дать простой ответ «да» или «нет» ... потому что это зависит от масштаба (количества наблюдающих объектов), частоты обновлений и размера обновлений. Например, собирать их все может быть ужасно неправильно, если размер обновлений может привести к потере буфера.

Клиент для MMORPG и игр FPS, как правило, разработан таким образом, что он визуализирует что-то, что «выглядит» правильно, даже если он не получает обновления для гораздо большего количества кадров обновления, чем это «нормально». При использовании ненадежной связи (UDP) вы можете просто ожидать потерять некоторое количество обновлений в пустоте, клиенты могут восполнить это, посылая более частые обновления, чем можно было бы использовать с надежным транспортом.

Из краткого обзора документации по socket.io видно, что он поддерживает как надежные, так и ненадежные (в своей терминологии изменчивые) пути связи.

Сначала я подхожу к этому, решая, с какой частотой нужны обновления ...

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

Независимо от того, что, вероятно, нет необходимости (как правило) отправлять обновления каждый кадр от клиента на сервер. Сам сервер может по своему выбору отправлять сообщения в каждом кадре, где он есть, или задерживать их (см. Формирование полосы пропускания, расстановка приоритетов и время жизни обновления).

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

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

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

Сбор сообщений для конкретной сущности для отправки одним сообщением может (в зависимости от реализации) уменьшить накладные расходы полосы пропускания при отправке сообщения (уменьшая ваши затраты) и наоборот (в зависимости от реализации, например сопоставления полей / значений, передаваемых строками), может увеличить пропускную способность требования по сравнению с более простым конкретным типом сообщения.

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

Я бы порекомендовал просмотреть все обновления, которые вы планируете тиражировать, например, большинство MMORPG и FPS не заботятся о том, чтобы отправлять нажатые игроком события X наблюдателям, если это не приведет к изменению состояния объекта, о котором они также знали. ,

Кристофер Ларсен
источник
3
+1 Отличный ответ. Я бы дополнительно предложил начать с простого и оптимизировать оттуда. Спам-сообщения, конечно, сходят с ума и видят, что ваша пропускная способность начинает падать. Вот почему хорошо проводить стресс-тестирование. Вы реализуете наивный возможный подход и проводите некоторое тестирование; вы делаете некоторые оптимизации; Вы снова тестируете стресс, далее оптимизируете, прополощите, повторите. Если оптимизация в первый день абсолютно тривиальна, продолжайте; но имейте в виду, что даже самые тривиальные оптимизации могут содержать предположения, которые впоследствии могут быть опровергнуты в производственной среде.
Инженер
5

Вот реальный пример: RuneScape «тикает» один раз каждые ~ 0,6 секунды. Вы можете прочитать об этом здесь . Я предполагаю, что это упрощает вещи с их точки зрения, так как в своих сценариях они, вероятно, задают время и задержки в тиках, а не в миллисекундах. И, конечно же, при такой большой / низкой частоте тиков пользователи с медленными подключениями не находятся в невыгодном положении по сравнению с другими игроками.

Ricket
источник
0

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

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

Kylotan
источник
Я бы не стал? Что насчет поз или чего-то такого, я должен быть уверен, что все клиенты видят одно и то же?
Ланбо
Совершенно непрактично гарантировать, что каждый клиент видит одно и то же, потому что для перемещения информации требуется время, у разных клиентов разная задержка в сети, они рендерится с разной скоростью и т. Д. Поэтому попытка заставить всех одновременно показывать один и тот же кадр обычно тщетные попытки Вместо этого вы можете просто попытаться убедиться, что они запускают одну и ту же анимацию примерно в одно и то же время, и этого достаточно.
Kylotan