Як впоратися з великою кількістю підйомів у грі MMO


26

Як обробляють такі ігри, як Minecraft або насправді будь-яка гра MMO, яка має пікапи?

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

Тож, що я думав, це те, що ви повинні "робити речі" тільки з пікапами, близькими до локального гравця, але все-таки це означатиме, що кожен кадр, який я маю перевірити, чи є якийсь інший елемент підбору, достатньо близький, що він повинен почати анімацію.

Моє актуальне питання: як інші ММО вирішили це питання?


9
Крім того, в контексті Minecraft, після того, як певна кількість елементів знаходиться досить близько один до одного (3+ одного і того ж елемента в тій же області блоків), сервер замінює 3 екземпляри згрупованим екземпляром, який містить тип блоку ( minecraft:dirt) і кількість (30), так що коли гравець достатньо близький, щоб забрати його, він просто додасть якомога більше підрахунку до інвентаря гравця. Якщо у гравця є лише 6 місць, а стек на 30 - на полі, гравець підніме 6, а стек на рахунку землі зменшиться до 24.
Zymus

6
@Zymus Варто зазначити, що фактично знизилася продуктивність галочок для помірної кількості викинутих предметів, оскільки всі вони постійно шукають сусідніх.
користувач253751

Відповіді:


48

Просто завантажуючи в пам’ять ті частини світу, які знаходяться поруч із програвачем. Все інше призупинено на жорсткому диску. Коли на відстані двох кілометрів лежить крихітний предмет, гравець не може його бачити і не може з ним взаємодіяти. Тому немає ніяких причин її оновлювати чи надсилати до GPU для надання. Чим менше об'єкт і його діапазон взаємодії, тим менший діапазон навколо плеєра, куди потрібно його завантажити.

Щодо з'ясування того, що є близьким до гравця: Це зводиться до того, щоб зберігати світ у структурі даних, оптимізованій для просторового пошуку. Хорошими кандидатами для цього є просторове хешування і багатовимірні дерева .


Дякую за швидку відповідь. Я думав про використання 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-Дерево, якщо хочете, але не очікуйте великих прибутків. Ви можете підрізати речі за допомогою манхеттенської дистанції, або можете сортувати свої речі у невеликій власній сітці ... але чому?

Перевірка відстані (дійсно відстань у квадраті, але для вас це однаково) - це лише два множення та доповнення (оптимізовано до MUL, MADD, так що насправді лише дві операції), після чого слід гілка або умовний хід. Це майже так само швидко, як і будь-яка інша операція, яка не обрізає цілі комірки сітки одночасно. Насправді це щось, що ви могли навіть зробити на GPU ...

Бачачи, як у вас буде кілька сотень, або щонайбільше декілька тисяч перевірок відстані на ту саму позицію (відстань у квадраті працює добре), у вас справді не виникає особливих проблем, просто роблячи цей розрахунок, тим більше, що це досить кеш- дружня ітерація над суміжною пам’яттю, а при умовних рухах - бруд дешевий. Щось на кшталт (псевдокод) rot = r[i] + 1; r[i] = ((dx*dx+dy*dy) < DIST_SQ) ? rot : r[i];. Це одна ітерація над масивом у кілька сотень значень на кадр. Комп'ютер не міг менше дбати про це, це суміжні навантаження та магазини, простий АЛУ, відсутність філій та лише кілька тисяч ітерацій.

Це (багато-до-одного) - це не той самий клас проблем (багато-до-багатьох), як на сервері. Дійсно, клієнт не проблема.


Вибачте, я подумав, що було зрозуміло, що я говорив про клієнта, коли я почав говорити про кадрах.
Алакану

1
Але клієнт ніколи не є проблемою. Клієнт дуже немасовий і дуже локальний, він повинен знати набагато менше, ніж сервер. В ідеалі клієнт знає вузол розділення простору (яким би він не був, скажімо, сітка), в якому знаходиться плеєр, і безпосередньо оточуючі, і все. Оновлення, таким чином, дуже скромні, якщо тисяча гравців не стоїть поруч. Зазвичай вам потрібні лише дельти для одного або двох об'єктів, а також вміст нового вузла сітки після переміщення в одну сторону на більшу половину ширини вузла. Все інше: не ваша проблема.
Деймон

1
Справа в тому, що бути занадто розумним може бути масово дурною ідеєю. Ваш світ обов'язково вже просторово розділений, з керованою кількістю об'єктів у кожному вузлі. Сучасні процесори (і тим більше GPU) хороші в послідовній обробці маси даних SoA. Вони не люблять неузгоджене розгалуження, і їм ще менше подобається некогерентний доступ до пам'яті - саме це і робить "лише процес поблизу". Для керованих чисел (кілька сотень, декількох тисяч) "обробити все" в межах однієї комірки є цілком адекватним, і, ймовірно, найкращим, що ви можете зробити.
Деймон

1
@Alakanu Це виглядає як детальна і повна відповідь на ваше запитання. Якщо ви думаєте, що це не відповідь, або ви її неправильно зрозуміли, або ваше питання настільки незрозуміло, що це було неправильно зрозуміло Деймон, я та всі люди, які підтримали цю відповідь.
Девід Річербі

2
@Alakanu Ви дійсно витрачаєте величезну кількість часу на скарги на людей, які намагаються вам допомогти. Удачі в цьому.
Девід Річербі

2

@ T.Sar пише в коментарі, що вам слід дізнатися про концепцію "завантаженої частини" Minecrafts для отримання додаткової інформації. Якщо ви це робите, майте на увазі, що це в Minecraft досить складно через людей, що будують машини в грі.

Далі йде дуже спрощена версія:

Світ розділений на квадратні регіони (шматки). У Minecraft також є розподіл по висоті, але більшості MMS цього не потрібно.

Клієнт гри лише піклується про регіони, близькі до гравця. Це набагато простіше, ніж намалювати коло навколо гравця, але досить добре.

У Minecraft регіони складають 16x16 блоків, і клієнт знає про 9x9 регіонів, по 4 регіони у кожному напрямку. (4 регіони схід + гравець регіону знаходиться в + 4 регіонах захід = 9 регіонів. Усього північ / південь)

У цих цифрах немає нічого магічного, використовуйте все, що має сенс у вашій грі.

Клієнт лише анімує речі всередині цієї області. Сервер обчислює лише такі речі, як мандрівні монстри в регіонах, близьких до якогось гравця.

Коли гравець гуляє всередині регіону, нічого особливого не відбувається, коли вони переходять межу регіону, "край анімації" пересувається на одну область. Потім клієнту потрібно запитати сервер про регіони, які він зараз бачить.

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

Сервер зберігає "заморожену версію" регіонів, яких не бачить жоден гравець. Якщо для цього потрібно багато пам’яті, можливо, ви захочете вивантажити їх через деякий час. Коли наступний гравець прибуває, регіон перезавантажується без падіння предмета. Наступного разу вам потрібно бути швидшим, програвач 1.


Відстань малювання регулюється, але в цьому випадку 8 шматок дорівнює 9x9 і є рішенням на стороні клієнта, він може повідомити сервер, щоби пришвидшити справи (тому сервер не надсилає дані, які клієнт не надаватиме). Також ... чи Дум і Квайк не вирішили цю проблему щодо відображення лише того, що має сенс?
SparK

Про відмову від занепалих предметів ... у Minecraft предмет "старіє" лише тоді, коли поруч є гравець. Таким чином, ви можете "зберегти" скинутий предмет у незавантажений шматок і отримати його пізніше.
Спарк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.