Що таке AI Map?
AI Map - площа на рівні, заповнена AI вузлами (нодами), що контролюють або обмежують переміщення NPC/мутантів (Далі - боти) за рівнем. У движку X-Ray існує два типи сутності: або щось онлайн, або офлайн. Онлайн зазвичай обмежується видимістю навколо РР (в оригіналі 150 метрів). В онлайні боти переміщаються по AI сітці, в офлайні вони переміщаються по точках - графпоинтам. Коли моб потрапляє в видимість ГГ, він переходить з офлайну в онлайн - це ті моменти, коли гра зависає іноді на кілька секунд і двигун перемикає об'єкти з офлайн в онлайн. AI карта має бути цільною, що не має розривів між нодами.
![]() |
AI Map у X-Ray SDK Level Editor |
На зображенні вище видно, як AI сітка огинає статичні об'єкти. Це не помилка редактора, так і має бути. Справа в тому, що моби в грі не бачать статичні об'єкти, вони бачать тільки карту AI і переміщаються строго по ній. Тому, якщо AI сітка проходитиме крізь статичний об'єкт (Дерево, автомобіль, будинок і т.п) то моб спокійно пройде крізь нього.
![]() |
З'єднання нодів між собою |
На зображенні вище видно з'єднання нодів між собою та напрямок кожного з них. Залежно кількості сторін, куди може вивести нод, ноду зараховується свій колір:
1) Повністю сірий нод - все 4 напрями;
2) Нід з 1 помаранчевим рубом - 3 напрямки;
3) Нід з 2 синіми ребрами - 2 напрямки;
4) Нід з 3 зеленими ребрами - 1 напрямок.
У найгіршому випадку нід має червоний колір, це означає, що нід не з'єднаний з основною сіткою. Його потрібно або видалити, або приєднати до карти.
Що таке графпоінти і навіщо вони потрібні?
Якщо моб стає офлайновим (Виходить із зони видимості ГГ, заданим в alife.ltx), то двигун переводить його в режим "оффлайн" і моб вирушає ходити по графпоінтах, від точки до точки переміщаючись, як би живучи своїм життям. Графпоінти – особливі точки, які існують лише на AI карті. Графпоінти видно в SDK, їх можна редагувати, розставляючи як завгодно або видаляючи їх, але в результаті після компіляції під формат гри, графпоінти не будуть частиною ігрового рівня або all.spawn: компілятор xrAI переводить графпоінти у вершини гри/рівня (в глобальний . Всі оффлайнові моби можуть переміщатися по цих точках, не зважаючи на переходи між рівнями (Як для ГГ), тобто для них графпоінти кожного рівня одна велика безшовна карта, по якій вони ходять, тому і відбуваються в сталкері багато оффлайн-події, особливо в модах (Типу АМК) без участі гравця, наприклад, NPC з Кордона пішов у Бар, на Складах убили сталкерів, поки ГГ був у Прип'яті і т.д. Слід зауважити, що розставляючи граф-поїнти в SDK, вони повинні бути строго на АІ-карті, не повинні провалюватися під сітку або висіти над нею, кожен граф повинен стояти на ноді - інакше будуть помилки.
![]() |
Виділено всі графпоінти на локації Кордон |
Корисна інформація щодо AI Map
1. При проекції на площину XZ є ноди 0.7х0.7
2. Ноди (або лв) нумеруються з півдня на північ, із заходу на схід.
3. Нульовий вертекс найзахідніший, проте не завжди найпівденніший.
4. Вертекс має координати X та Z кратні 0.7 (розміру ноди).
5. Якщо лв розрізняються лише координатою У (на різній висоті), то нумерація чергується (що нумерується першим, верхній чи нижній, поки не відомо). (by Desertir)
Загальний максимальний розмір карти в середньому включає 3.000.000 - 3.500.000 млн. щільно заповнених аї-нодів, що дорівнює рівню приблизно рівному 1.3 х 1.3 км ( На даний момент GSC виклали вихідні коди у вільний доступ, що збільшує ймовірність збільшення цього обмеження у найближчому майбутньому ). Так само слід враховувати і точки для офлайну - графпоінти, чим більше аі-сітка, тим більше має бути їхня щільність. Обмеження компіляторів xrAI ( можливо, на даний момент ) не дають можливість зробити великий рівень, який можна наповнити життям, тому що якщо перевищити середнє значення нодів у 3 млн і більше 400 графпоінтів - компілятор валитиметься з помилками. Звичайно, ніхто не заважає зробити великий рівень сам по собі як такий (Геометрія), тим нещодавно випущені х64 компілятори дозволяють тягнути більш важку геометрію рівня, але наповнити його подіями не вийде, або потрібно обмежувати розмір карти AI. (Актуально на серпень 2016 року, можливо, коли-небудь картина зміниться)
- Сітка всередині файлу є лінійним масивом з усіх вузлів. Вони нумеруються від нуля. Самих вузлів може бути теоретично 2 у ступені 32, але реально набагато менше, а головне - розмір сітки у плані диктується ще одним обмеженням, яке буде зрозуміло далі.
- Положення окремого вузла задається двома цілими числами: 16 біт для координати Y за висотою та 24 біти на дві упаковані координати XZ у плані. Назвемо ці числа NY та NXZ . Для переведення цих чисел у реальні геометричні координати (X, Y, Z) у заголовку файлу записані такі дані:
Розмір рівня (точніше сітки) по вертикалі, назвемо HY розмір елемента сітки по горизонталі (вузол сітки квадратний), назвемо DXZ розміри сітки рівня в боксу, заданого вектором двох вершин. Назвемо їх (X0, Y0, Z0) та (X1, Y1, Z1) . При цьому розмір по вертикалі HY завжди збігається з розміром, отриманим з віднімання цих двох векторів Y1-Y0 (тобто є надмірність даних). Розміри боксу в плані X1-X0 та Z1-Z0 повинні бути кратні елементу комірки в плані DXZ .
Алгоритм переведення упакованих числа в координати такий:
По вертикалі завжди маємо максимально можливе число рівнів 65536 (два байти), і відповідно мінімальний крок по вертикалі буде
DY = HY / 65536
Положення вертексу по вертикалі буде відповідно
Y = Y0 + DY * NY або, що теж саме
Y0 + NY * HY/65536
Для отримання координат по горизонталі треба розпакувати 24 біти NXZ . Поступаємо так:
Спершу обчислюємо кількість вертексів по X і Z (точніше розмір боксу у вертексах, самих вертексів може бути меншим):
СX = (X1 - X0) / DXZ
СZ = (Z1 - Z0) / DXZ
Тепер як би приймаємо, що всі позиції вертексів у плані впорядковані в набір горизонтальних рядків і пронумеровані наскрізним чином приблизно як показано на малюнку:
![]() |
24-бітне поле NXZ - це і є номер наскрізної нумерації. Для отримання координат треба виділити номер рядка NX і стовпця NZ .
NX - це по суті номер рядка, відповідно:
NX = результат цілого чисельного поділу NXZ/CZ
NZ - це позиція всередині рядка і відповідно:
NZ = залишок від поділу NXZ/CZ
Тепер самі координати отримуємо просто:
X = X0 + NX * DXZ
Z = Z0 + NZ * DXZ
Тепер що випливає з такого алгоритму. Найголовніше, що розміри сітки в плані "у комірках" має обмеження, а саме:
NX * NZ <= 16777216 (2 у ступеню 24)
При цьому не важливо, наскільки реально в плані рівень покритий сіткою, важлива саме відстань між найбільш віддаленими точками сітки. Для прикладу, сітку рівня можна вписати в плані в квадрат 4096х4096 осередків або прямокутник 8192х2048 або прямокутник 5592х3000 і т.д. Ось це і накладає обмеження на максимальний розмір рівня, а точніше тієї його частини, що покрита сіткою і доступна для неписів.
Розмір осередку зазвичай 0.7 . Відповідно, для такого розміру комірки та квадратної у плані області сітки максимальні геометричні розміри будуть 4096*0.7 = 2867.2 ігрових метрів.
До цього можна додати, що вертекси в цьому масиві відсортовані за зростанням всіх трьох координат для того, щоб двигун міг їх шукати бінарним пошуком. (by Malandrinus)