У фортеці карликів у будь-який момент у грі ви можете мати сотні гномів, тварин, гоблінів тощо, кожен зі своїм складним AI та рутинним режимом. Моє запитання: як це не призводить до помітного уповільнення? Чи кожен Гном працює у своїй власній нитці?
У фортеці карликів у будь-який момент у грі ви можете мати сотні гномів, тварин, гоблінів тощо, кожен зі своїм складним AI та рутинним режимом. Моє запитання: як це не призводить до помітного уповільнення? Чи кожен Гном працює у своїй власній нитці?
Відповіді:
Будь-яка система, яка мала потік для кожного з такої кількості символів, втратила б ресурси дуже швидко. Нитки можуть дати вам доступ до додаткових процесорних ядер, але вони нічого не роблять по суті більш ефективним, і вони надходять з накладними витратами.
Проста відповідь - просто бути ефективною щодо обробки кожної сутності в грі.
Карликова фортеця не є відкритим кодом, і хоча існує велика кількість гіпотез та зворотної інженерії, які можуть втрутитися в те, як це все працює, я замість цього зосередитимусь на деяких основних методах оптимізації 3D (не 3D графіки, 3D світу) одного типу.
Як і у всіх відеоігор, є багато диму і дзеркал, які створюють ілюзію складності з простих правил і систем. Вони варіюються від використання простих випадкових чисел для безцільного руху на всьому шляху до попереднього випікання сітки вузлів високого рівня для наведення маршруту.
Якщо говорити про нанесення маршрутів, то це може бути дуже важкою проблемою для вирішення великих просторів, як, наприклад, карта DF (цілком 768x768x64 IIRC), проте проблему можна спростити та прискорити таким чином:
Я не буду висвітлювати основи проходження маршруту. Більшість негідників використовують A *, але є й інші методи, як шкіру кота. Мммм Котяча шкіра ..
Одна з найважливіших речей, яка змушує підрозділи ДФ з'являтись та відчувати себе живими - це їхній особистий список цілей. Насправді багато ігор, що мають шахрайство, мають це на базовому рівні. По суті кожен підрозділ має список бажань (а для ваших dorfs завдань, які вони можуть вибрати, які ви просите виконати), і вони вибиратимуть їх залежно від їх особистості (статистика.)
Деякі завдання мають вимоги. Зробити шкіряну спідницю вимагає, щоб dorf був у такому магазині, де є X предметів. Тож усі вони перевіряються та додаються як завдання до їх списку. Просто як це.
Оскільки більшість часу підрозділ буде в дорозі, перевірки того, що роблять підрозділи, можуть бути дуже швидкими, лише кілька одиниць будуть робити вибір у будь-який момент, і тому загалом немає сповільнення навіть на сотні чи тисячі одиниць. І пам’ятайте, в DF все - від бджіл до троглодитів до дерев - це одиниці.
Здійснюючи додаткові дослідження, зрозуміло, що DF, як це дивно, займається жахливою роботою в пошуку шляху. Це не розбиття карти на шматки, це розбиття карти на пов'язані між собою сегменти або ділянки (що краще, ніж нічого точно), тому моя вище оцінка є ще менш прикладом того, як працює DF, ніж я думав. :) Що не означає, що DF - це щось менш дивовижне з мільйона інших причин.
Це свідчить про те, що важливо в грі - гра. Не графіка, не чудове програмування, не чудова написання, не чудова музика, навіть інтерфейс; нічого іншого навіть 1% не так важливо, як сама гра.
З цієї сторінки :
Добре [нарізка] з мого кінця виглядає приголомшливо, оскільки є метрична тонна персонажів, які роблять це відразу.
ТА: Гноми здебільшого пересуваються з A *, із звичайною старою евристикою вулиць. Хитра частина полягає в тому, що він насправді не може зателефонувати на A *, якщо вони не знають, що зможуть потрапити туди заздалегідь, або це в кінцевому підсумку затопить карту і вбиває процесор.
Я не знаю, чи це точно, як він запобігає «затопленню карти» , але звичайний спосіб зробити це в іграх - це внесення змін до A *, що називається Ієрархічним Шляхом пошуку A * , або HPA *. Ідея полягає в тому, щоб розбити сітку на багато менших, але більших шматочків, а потім скористатися A *, щоб знайти найкращий шлях від кожного шматка до сусідніх шматочків. Ви можете використовувати це для створення набагато меншого графіка, над яким слід виконувати A * для кожної одиниці.
Ви також можете згрупувати ці шматки в ще більші шматки, звідки походить "ієрархічний".
Цей алгоритм знаходить лише оптимальні шляхи, але для таких ігор, як Dwarf-Fortress, як правило, добре. Все одно гарантовано знайти шлях, якщо такий існує; а коли шляху немає, воно лише заповнить менший графік, заощадивши величезну кількість часу.
Існує також абстракція HPA *, яка має справу з одиницями, які можуть проходити через деякі місцевості, але не інші (наприклад, скелі, по яких повітряні установки можуть переходити, але наземні установки не можуть) . Це називається НАА * , і є дуже доступна стаття пояснюючи це тут .
Ви можете прочитати більше про різні алгоритми прокладання маршруту тут .
Якщо що, то навпаки - вся справа працює на одній нитці, і тепер вона потрапляє в точку, коли це стає фактором блокування (востаннє я перевіряв!)
Причина, що це швидко, полягає в тому, що немає фантазійної графіки. Це оманливо, але головне, що сповільнює роботу, - це малювання речей (придумати дві третини кадру в заголовках AAA). Оскільки карликова фортеця є досить базовою, то решту часу вона приділяє займанням цікавих справ.
Я не знаю, як кодується DF, але кількість AI мене не дуже вражає, тому що те, що люди часто переглядають, що AI не потребує точності . Цілком реально робити більшість матеріалів лише кожні кілька секунд. Крім того, можливо використовувати неточні розрахунки. Недосконалість економить багато результатів . Ви можете запустити процедуру прийняття рішень у 100 одиниць кожні 100 мс, або ви можете виконувати її на 1000 одиниць щосекунди, це займе стільки ж часу процесора, але добре ... у вас є 10 разів більше одиниць.
Ось простий приклад того, як можна обробляти багато одиниць:
int curUnit;
Array<Unit> units;
[...]
while([...]) // Game Loop
{
[...game logic...]
// process 10 AIs per Frame
for(int i=0; i++; i<10)
{
curUnit++
if(curUnit == units.length()) curUnit=0;
if(curUnit < units.length())
units[curUnit].processAI();
}
// Update the position of all units, this should be as optimized as possible
foreach(Unit& unit in units){ unit.move(); };
[...graphics...]
}
ШІ стане все менше і менше реагувати, чим більше є, але гравець, ймовірно, помітить це лише у крайніх випадках.