Как часто сохранять состояние игрока в постоянных онлайн-играх?

9

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

Имеет ли смысл сохранять координаты и состояние игрока при каждой отправке? Мой сервер node.js может сделать это легко, не блокируя ответ, и я хочу использовать базу данных Mongo, но, возможно, более уместно делать это один раз в секунду и в общесерверном событии, собирая все сразу?

Lanbo
источник
Я сохраняю состояние игры каждые 10 секунд. Я думаю, этого достаточно, это остается незамеченным (и я использую свой сервер MMORPG на моем нетбуке с 512 МБ ОЗУ).
Jcora

Ответы:

10

Я имею в виду традиционную MMORPG, такую ​​как World of Warcraft.

Сохранить после каждой команды от каждого игрока и автономной вещи (например, NPC)

  • Постоянное резервное копирование. Сервер может выйти из строя в любой момент, и состояние игры сохраняется до этого момента (или, во всяком случае, настолько недавно, насколько это возможно).
  • Влияние на производительность сервера; даже если он неблокируемый (то есть в другом потоке), даже если база данных находится на другом сервере, это обработка, которую иначе вы бы не делали. Если он неблокируемый, как вы говорите, то другой поток должен обработать его, и этот поток может быть занят чем-то другим.
  • Увеличение дискового ввода-вывода, что увеличивает риск / частоту отказов. Это особенно важно, если вы используете SSD для хранения данных, учитывая их меньший срок службы.
  • Если вы выгружаете базу данных на другой сервер, то увеличивается пропускная способность; это может быть проблемой, если вы платите за пропускную способность, и если она не на отдельной сетевой карте, она потребляет ресурсы, которые лучше использовать для обработки трафика игрока.
  • Что произойдет, если сервер все больше отстает в сохранении состояния этих команд? Т.е. если поступит больше команд, чем их можно сохранить, они накапливаются в очереди? Эта очередь переполняется и вызывает ошибку? Вы останавливаете все, чтобы очередь могла наверстать упущенное?
  • Мне кажется, что этот подход, хотя и звучит просто, должен быть тщательно спланирован. Например, последовательные команды, которые зависят друг от друга, должны быть сохранены вместе; в противном случае в середине команд может произойти сбой, и будет сохранена только одна, но не другая. Подумайте, выполняют ли два игрока сделку и сохраняются ли на диске две команды: «добавить 1 предмет получателю» и «вычесть 1 предмет из отправителя». Если сбой происходит после первой команды, но до сохранения второй команды, у вас есть дублирование элемента. (если заказ отменен, значит у вас есть потерянный предмет)

Периодически сохраняйте все

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

Сохранить персонажа при выходе из системы (больше ничего не сохранять)

  • Самое важное для игрока - это его персонаж, который включает в себя предметы, которые у него есть, навыки, которые они заработали, список своих друзей и так далее. Если они убивают монстра, и добыча находится на земле перед ними, а затем сервер выходит из строя, они будут немного расстроены из-за того, что у них не будет возможности забрать их добычу, но они справятся с этим. Так что просто сохраняйте важные вещи и не парьтесь с мелочами. Не сохраняйте позиции NPC, например; если сервер выходит из строя, когда он возвращается, они появляются в общей области, в которой они должны находиться. Исключением, конечно, являются любые «умные» NPC, которым по какой-то причине необходимо оставаться в том месте, где они находятся. были когда сервер вышел из строя.
  • Кроме того, игрок не должен входить в систему слишком много часов за раз (обратите внимание, что здесь я рассматриваю «возвращение в лобби» как выход из системы). В конечном итоге им потребуется сделать перерыв в ванной или получить еду или быть прерванным родителями / друзьями / кем бы то ни было или спать. Таким образом, они действительно не должны входить в систему без перерыва больше, чем, скажем, 8 часов даже для самого хардкорного геймера. Если «игрок» вошел в систему в течение действительно длительного периода времени, есть большая вероятность, что это либо несколько человек, либо бот, и ни один из них не является желательным или нормальным.
  • Кроме того, ваш процесс выхода из системы уже должен проверять такие вещи, как вышеупомянутые последовательные команды. По сути, он уже должен упаковывать персонажа, так что, очевидно, самое подходящее время - сбросить его на диск.

Заключительные мысли

  • Очевидно, я поддерживаю последний подход, но я старался быть беспристрастным во всех трех.
  • Трудно сказать, какой из первых двух методов является более расточительным. В первом методе, если персонаж отправляет несколько команд перемещения, каждая из них будет сохранена на диск и перезаписана, когда они могут быть объединены в одну. Но при втором способе, если у вас есть половина вашего населения, его позиции сохраняются на диск, даже если они точно такие же, как и после последней операции резервного копирования. В третьем случае вполне возможно, что кто-то сможет войти в систему и сразу же выйти из нее, но чаще всего многое в игроке изменится, поэтому расточительность кажется минимальной.
  • Имейте в виду, что это исключительно для резервного копирования в случае сбоя, и сбой должен быть абсолютно минимизирован. Хорошо обрабатывать это исключение, но в конце концов, если сервер выйдет из строя, некоторые данные будут потеряны, а некоторые игроки будут расстроены. Так что просто реализуйте любой метод, который вы можете, как вы думаете, самый простой или лучший, и продолжайте.
  • Не полагайтесь на это как на сохранение по умолчанию; вставьте красивую кнопку выключения в серверное приложение, которое изящно закрывает соединения и записывает все в базу данных. Используйте это на обычной основе.

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

Ricket
источник
4
Из того, что я лично наблюдал, коммерческие ММО используют комбинацию всех трех из них. Сохранения происходят после важных событий и действий, таких как убийства / мародерство / торговля боссом, периодически, чтобы не пропускать некритические действия (и не наказывать тех, кто вошел в систему в течение длительных периодов времени), и всегда при выходе из системы. Как правило, одного метода недостаточно. Почти все эти методы основаны на базе данных в стиле SQL, которая прозрачно резервируется и восстанавливается в случае сбоя оборудования.
NtscCobalt
@NtscCobalt - я был с вами до "базы данных в стиле SQL". SQL действительно требование? Что насчет NoSQL?
beatgammit
@tjameson Мой комментарий был написан до того, как я коснулся NoSQL. Я только пытался сказать, что вы не должны накатывать свой собственный формат, но в любом случае я бы по-прежнему рекомендовал SQL, поскольку вы должны знать схему заранее (или быть ленивым и использовать Entity-Key-Value), и согласованность важнее, чем возможность разбить эти данные. См. Stackoverflow.com/questions/7339374/… для получения дополнительной информации.
NtscCobalt
1

Я предполагаю, что это зависит от типа игры и количества трафика между игроками и сервером.

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

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

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

JMellow
источник
1

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

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

Лунин
источник
Да, отсюда и необходимость регулярно отправлять на сервер обновления таких значений, как position и XP. Чем дольше вы его оставляете, тем более спорным становится вопрос о том, собрал ли игрок фактически сообщенные дельты или нет. Если вы ограничите эти периоды «регистрации», это будет намного проще контролировать / контролировать.
Инженер
Проблема определения, когда игрок вышел из браузера в длительной браузерной игре, на самом деле не является тривиальной.
Ланбо
Я согласен, что это нетривиально, но это проблема, которую вы должны решать так или иначе в большинстве игр, даже если вы просто решаете, когда их аватар больше не появляется. Как только это будет сделано, должно быть относительно простым заняться этим сценарием и сохранить свою последнюю действительную позицию.
Лунин