Как обрабатывать большое количество пикапов в MMO-игре

26

Как с ними справляются такие игры, как Minecraft или вообще любая MMO-игра, в которой есть звукосниматели?

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

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

Мой актуальный вопрос: как другие ММО решили эту проблему?

Alakanu
источник
9
Кроме того, в контексте Minecraft, после того, как определенное количество элементов достаточно близко друг к другу (3+ одного и того же элемента в одном и том же блок-пространстве), сервер заменяет 3 экземпляра сгруппированным экземпляром, который содержит тип блока ( minecraft:dirt) и счет (30), так что, когда игрок находится достаточно близко, чтобы поднять его, он просто добавляет как можно больше счета в инвентарь игрока. Если у игрока есть место только для 6 предметов, а стопка из 30 находится на земле, игрок соберет 6, а
Зимус
6
@Zymus Стоит отметить, что на самом деле снижено быстродействие тиков для умеренного количества выпавших предметов, потому что все они постоянно ищут близлежащие.
user253751
Прочитайте en.wikipedia.org/wiki/Occlusion_culling
RJFalconer

Ответы:

48

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

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

Philipp
источник
Спасибо за быстрый ответ. Я думал об использовании Unity, так как полагаю, что для проверки триггерных коллайдеров используется какое-то пространственное разбиение, поэтому я бы создал один коллайдер большого круга вокруг моего персонажа, и каждый элемент внутри него был бы «анимированным». Это способ реализации вашего ответа? Поправьте меня, если я ошибаюсь, ура!
Алакану
2
@Alakanu Это может быть использовано, если вы хотите, чтобы объекты были видны на больших расстояниях, но выполняли определенные интенсивные вычисления в непосредственной близости от игрока (и просто вращать что-то вокруг своей оси y не должно быть очень дорого). Но реальной проблемой при реализации игры с открытым миром в Unity является интеллектуальное создание и уничтожение игровых объектов, пока игрок движется по миру (или даже лучше: используйте объединение объектов вместо создания и уничтожения).
Филипп
Да, в этой ситуации объединение объектов обязательно :) Хорошо, большое спасибо!
Алакану
3
@Alakanu Вы можете проверить концепцию Minecraft «Loaded Chunks» для получения дополнительной информации о том, как этот ответ применим к этой игре.
Т. Сар - Восстановить Монику
1
Это касается не только пикапов. Любой объект, который находится слишком далеко от игрока, может быть обработан таким образом. Иногда даже объекты, которые находятся рядом с игроком. Представьте себе дом с полным интерьером, но нет необходимости рендерить, пока вы на самом деле не войдете в дом.
Зибелас
22

У вас есть две очень разные вещи для управления:

  1. Сервер должен управлять всем миром авторским способом. Для этого необходимо общение с N клиентами (где N "массивный").

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

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

Серверу не нужно ни знать, ни заботиться о ротации пикапов или подобных деталях. С чего бы это?

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

С точки зрения сервера необходимо знать, что вы копали в (30, 40, 50) в узле, в котором вы находитесь, и решает, что это порождает, например, три объекта типа 5 или один объект типа 7 с счет 3. Это все, что его волнует, и это все, что он говорит вам. Он также будет включать эту информацию в данные, отправляемые кому-либо, перемещающему свою область интереса через ячейку сетки позже (при условии, что она все еще там к тому времени).

Клиенту говорят, что там появилось три объекта, бла-бла. Теперь, показывает ли клиент карту ASCII-искусства, где теперь есть буква «D», или показывает вращающуюся кучу грязи, все равно. Независимо от того, имеют ли сваи разные повороты или вращаются только те, которые находятся рядом с вашим игроком, это тоже одно и то же. Это просто материал, который отображается на вашем мониторе, это ни на кого не влияет.

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

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

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

Проверка расстояния (действительно квадратное расстояние, но оно то же самое для вас) - это просто два умножения и сложение (оптимизированное для MUL, MADD, так что на самом деле это просто две операции), за которым следует ветвление или условное перемещение. Это почти так же быстро, как и любая другая операция, которая не удаляет целые ячейки сетки одновременно. На самом деле, это то, что вы могли бы даже сделать на GPU ...

Видя, как у вас будет несколько сотен или самое большее несколько тысяч проверок расстояния на одну и ту же позицию (квадратное расстояние отлично работает), у вас действительно не возникнет особых проблем с выполнением этого вычисления, тем более, что это скорее кэш-память. дружественная итерация по непрерывной памяти, и с условными ходами, это очень дешево. Нечто подобное (псевдокод) rot = r[i] + 1; r[i] = ((dx*dx+dy*dy) < DIST_SQ) ? rot : r[i];. Это одна итерация массива из нескольких сотен значений на кадр. Компьютер не должен заботиться об этом, это непрерывные загрузки и хранилища, простой ALU, нет веток и всего несколько тысяч итераций.

Это (многие-к-одному) не тот же класс проблем (многие-ко-многим), что и на сервере. На самом деле, клиент не проблема.

Damon
источник
Извините, я думал, что было ясно, что я говорил о клиенте, когда я начал говорить о частоте кадров.
Алакану
1
Но клиент никогда не является проблемой. Клиент очень не массивный и очень локальный, ему нужно знать намного меньше, чем серверу. В идеале клиент знает узел пространственного разделения (где бы он ни был, скажем, сетка), в котором находится игрок, и непосредственно окружающие его, и все. Обновления, таким образом, очень скромные, если тысячи игроков не стоят рядом друг с другом. Обычно вам нужны когда-либо только дельты для одного или двух объектов, а также содержимое нового узла сетки после перемещения в одном направлении более чем на половину ширины узла. Все остальное: не ваша проблема.
Деймон
1
Дело в том, что быть слишком умным может быть очень глупой идеей. Ваш мир обязательно уже пространственно разделен, с управляемым количеством объектов в каждом узле. Современные процессоры (и тем более графические процессоры) способны последовательно обрабатывать большие объемы данных SoA. Они не любят некогерентное ветвление и еще меньше любят некогерентный доступ к памяти, что, впрочем , и делает «только процесс рядом». Для управляемых чисел (несколько сотен, несколько тысяч) «обработать все» в одной ячейке вполне достаточно, и, вероятно, это лучшее, что вы можете сделать.
Деймон
1
@Alakanu Мне кажется, это подробный и полный ответ на твой вопрос. Если вы думаете, что это не ответ, либо вы неправильно поняли его, либо ваш вопрос настолько неясен, что его неправильно поняли Дэймон, я и все люди, которые проголосовали против этого ответа.
Дэвид Ричерби
2
@Alakanu Вы действительно тратите огромное количество времени, жалуясь на людей, которые пытаются вам помочь. Удачи с этим.
Дэвид Ричерби
2

@ T.Sar пишет в комментарии, что вы должны изучить концепцию Minecrafts «загруженный кусок» для получения дополнительной информации. Если вы это сделаете, имейте в виду, что это довольно сложно в Minecraft из-за людей, которые строят машины в игре.

Ниже приведена очень упрощенная версия:

Мир делится на квадратные области (куски). В Minecraft также есть разделение по высоте, но большинству ммос это не нужно.

Игровой клиент заботится только о регионах, близких к игроку. Это гораздо проще, чем нарисовать круг вокруг игрока, но достаточно хорошо.

В Minecraft регионы имеют размеры 16x16 блоков, и клиент знает о 9x9 областях, по 4 области в каждом направлении. (4 региона восток + игрок региона находится в + 4 регионах запад = всего 9 регионов. Тот же север / юг)

В этих числах нет ничего волшебного, используйте то, что имеет смысл в вашей игре.

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

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

Нет ничего плохого в наличии нескольких вложенных ограничений анимации. Например, анимированный предмет падает в области 3х3, блуждающие монстры в области 5х5 и просто показывают пейзаж в области 9х9.

Сервер хранит «замороженную версию» регионов, которые ни один игрок не видит. Если это занимает много памяти, вы можете разгрузить их через некоторое время. При следующем прибытии игрока регион перезагружается без выпадения предмета. Ты должен быть быстрее в следующий раз, Игрок 1.

Стиг Хеммер
источник
Расстояние отрисовки можно регулировать, но в этом случае 8 фрагментов имеют размер 9x9 и являются решением на стороне клиента, хотя они могут информировать сервер об ускорении процесса (поэтому сервер не отправляет данные, которые клиент не будет отображать). Кроме того ... Разве Doom и Quake не решили эту проблему с рендерингом только в чем смысл?
SparK
О сбросе выпавших предметов ... в майнкрафте предмет только "стареет", когда рядом находится игрок. Таким образом, вы можете «сохранить» брошенный элемент в незагруженном блоке и получить его позже.
SparK