"Зонування" районів на великій карті плитки, а також підземелля


10

У моїй грі є така карта, як у Minecraft, таким чином, як вона псевдобезпечна і генерується випадковим чином. І великий. Скажімо, користувач дослідив зону 1000х1000 (тут 2D), так що це 1 000 000 плиток.

Очевидно, я не зможу все це зберегти в пам'яті. Також я не хочу просто ігнорувати все з 10 плиток чи будь-якого радіусу - і те й інше не оновиться (усі NPC, можливо, реактивні плитки), і мені доведеться працювати з незручними позиціями, такими як 1382,12918.

Отже, якби я розділив його на шматки або зони або, як би там не було сказати, 64х64 плитки, я повинен був би зберігати кожну плитку та позицію об'єкта, наприклад:

Чанка а, б. Позиція x, y.

Але що робити, якщо я захотів підземелля тощо? Так єдина плитка, яка веде до підземелля на 40 поверхів, кожна з площею 40х40. Я не можу точно зберігати їх на одній карті.

І є сторона пам'яті; скільки я можу потенційно зберігати в пам'яті одночасно розумно? Я міг робити плитки за ідентифікатором досить легко і мав там нормальний 2D масив. Або, знову ж таки, є більш ефективне рішення, ніж наявність файлу даних типів плиток ? Так що для 64x64 ... це буде лише 20K або що завгодно. Я хотів би, щоб якомога більше оточуючих було завантажено для найбільш реалістичного оновлення. Але я не знаю, на які обмеження я можу потрапити, не ставши привичками пам’яті.

Відповіді:


9

Хоча я погоджуюсь з думками: "не хвилюйтеся з цього приводу, якщо це не доведена проблема", я думаю, що варто заздалегідь подумати над тим: ретро пристосування рішення набагато болючіше. І так, лише оновлення плиток "поблизу" - це шлях. Але ефективність зберігання та адресації предметів у вашому ігровому світі дуже важлива з міркувань продуктивності.

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

Стандартним рішенням розрізненої задачі набору даних є відокремлення індексу / адресації від фактичного зберігання даних. Тож якщо плитковий предмет дорогий, зберігайте його в компактному вигляді (наприклад, плоский масив). Але дозвольте його індексувати через більш дешевий об’єкт. У своїй найпростішій формі це може бути 2D (або 3D) матриця, яку ви можете легко індексувати за координатами, але кожен елемент у матриці - це просто індекс. Потім ви використовуєте цей індекс для пошуку фактичного вмісту плитки в окремому компактному масиві. Якщо вміст плитки ще не існує, додайте їх у кінець масиву та збережіть індекс у тривимірній матриці.

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

Ви можете отримати ще більшу ефективність зберігання, ввівши додаткові шари непрямості. Скажімо, ви організовуєте свою плитку в шматки, а шматки мають деталізацію 64x64x64. Враховуючи плитку в 125, 1, 132, ви знаєте, що вона належить шматку (1,0,2). Отже, у вас є світ, який складається з компактного масиву фрагментів і матриці індексів фрагмента (-1, якщо фрагмент не існує). Вміст кожного фрагменту (якщо він присутній) - це матриця розмірами 64x64x64 індексів плитки (-1, якщо плитка ще не існує) та компактний масив використаних плиток. Таким чином, ви не спалюєте велику кількість індексів плитки для шматок, які ніколи не використовуються. Дотримуючись такого роду підходу та підбираючи розумні номери для деталізації шматка, ви зможете масово масштабувати свій Всесвіт і тримати контроль пам'яті. Насправді, якщо ви робите шматки 32x32x32,

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


Я б застеріг усіх, хто в майбутньому стикається з цим питанням: хоча в цій публікації нічого невірно, це справді жахливо для такої гри, як Minecraft, яка має нестримний світ. (І г-н Кранкі каже так само.) Ваш світ від цього виграє лише в тому випадку, якщо він має декілька сотемів і багато промальовок , а не кілька соматів і багато спорожнень .

1
Я від душі погоджуюся, що накладні витрати, пов'язані з підтримкою розрідженого рішення для зберігання набору даних, досить високі, тому ви б пішли на це, лише якщо баланс був явно перекошений у бік розрідженості. Ключовими факторами тут є: вартість даних-елемент та ймовірність того, що дані-позиції-позиції-не використовуються. У Minecraft є масивний, масивний набір даних про потенційні можливості (деякі великі кількості плиток у кожному напрямку). Фактична частка використовуваного потенційного ігрового світу невелика. Навіть незважаючи на те, що ви рухаєтесь великими деталями, рухаючись по всьому світу, це все ще є невеликою частиною потенційних даних.
MrCranky

1
Що відрізняє Minecraft від того, що вартість на одиницю невелика - можливо, це один байт сховища? Одне значення вказує "нічого там", решта - це типи блоків, і ви можете легко помістити це в байт. Таким чином, у вас не було б індексу до одного блоку, це просто шалено, індекс набагато більший, ніж просто зберігання фактичного значення блоку. Але розрізнені правила набору даних все ще працюють на вищих рівнях. Кожен фрагмент (наприклад, 64x64x64) дорого зберігається (256 КБ блоків), тому, якщо ви можете використовувати одне невелике значення, щоб вказати його відсутність, або його адресу, якщо вона існує, то ви зберегли масове зберігання.
MrCranky

6

Чому ви не можете зберігати мільйон плиток в пам'яті? Навіть мій телефон має 256 Мб оперативної пам’яті; мільйон порожніх плиток буде що, 4-32 МБ?


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

2
Набагато простіше просто ігнорувати набір плиток для оновлень, ніж це стосуватися якихось рішень для підключення диску. Просто .. ігноруй їх. Не оновлюйте плитки більше, ніж на відстані X від відомого актора.

2
@TheCommunistDuck Єдине, що важливо - це загальний об'єм пам'яті, який використовується для зберігання плиток, а не кількість плиток.
Джастін

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