Реверс-інжиніринг процедурної генерації No man's Sky



No man's Sky — це гра про дослідження космосу, в якій використовується технологія процедурної генерації ігрового оточення і ресурсів (текстур, моделей, рельєфу тощо). Я був у захваті, коли оголосили про її розробці в 2013 році, не тільки через самої гри, але в основному із-за можливості вивчити ігрові файли і дізнатися, як вона працює. Після випуску гра отримала суперечливі відгуки, але мені все одно цікаво, що ж відбувається у неї всередині.

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

Геометрія
Отже, у грі файли геометрії (вершин, буферів індексів тощо) зберігаються у файлах з розширенням ".GEOMETRY.MBIN". Вже з допомогою цих файлів можна створити досить прості парсери, перетворюють геометрію для роботи З 3D-моделювання. Але цього файлу недостатньо самого по собі. Такий файл з геометрією використовується як контейнер для чистих геометричних даних.

Гра завантажує ресурси як сцени. Це означає, що всі ресурси моделей визначаються як файли окремих сцен з власними ієрархіями об'єктів, кількома частинами сіток, декількома типами об'єктів (шарніри, джерела освітлення, точки взаємодії, колізії, інші файли сцени) і т. д. Цей тип інформації зберігається у файлах ".SCENE.MBIN". Вони є справжніми дескрипторами конкретної сцени, і зазвичай такі файли посилаються на один контейнер геометрії, з якого всі частини сіток в сцені отримують відповідну інформацію про геометрії.

Поки в цьому немає нічого нового. Така ж ситуація в різних ігор. No man's Sky відрізняється від інших ігор (принаймні, раніше я з таким не стикався) тим, що в цьому файлі сцени не просто одне готове істота, яку можна створити в грі при певних умовах, тут вступає в справу процедурна генерація.

Я коротко поясню, як це виглядає, приклавши кілька зображень із створеного мною NMS Model Viewer.


Модель трицератопса

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

Найважливіше в цих даних — фактичні назви об'єктів. Можна чітко побачити, що є певний зв'язок між ними і способом, яким гра дізнається про те, як комбінувати ці частини і виключати непотрібні при створенні моделі.

Помітивши це, я почав шукати інші файли, які можуть керувати організацією сцени, і виявилося, що це файли ".DESCRIPTOR.MBIN". Не у всіх моделей є такі файли. З'ясувалося, що вони є тільки у процедурно генеруються моделей, а у статичних моделей (таких як модель астронавта або матеріали, створені для трейлера) їх немає.

Коли я почав реверс-інжиніринг формату файлів NMS, я виконував парсинг цих дескрипторів файлів, але вони постійно здавалися мені якоюсь нісенітницею, і я не міг зрозуміти, що ж вони роблять. Після парсинга сцен я вже усвідомив, що потрібно шукати, і повернувся до цих дескрипторів файлів. Вони дуже сильно схожі на файли сцен. У них застосований той же спосіб визначення частин і всього іншого, вони можуть посилатися на інші частини сіток або цілі файли сцен. Ці файли працюють наступним чином:

<Data template="TkModelDescriptorList">
<Property name="List">
<Property value="TkResourceDescriptorList.xml">
<Property name="TypeId" value="_HEAD_" />
<Property name="is invalid">
<Property value="TkResourceDescriptorData.xml">
<Property name="Id" value="_HEAD_ALIEN" />
<Property name="Name" value="_Head_Alien" />
<Property name="ReferencePaths" />
<Property name="Chance" value="0" />
<Property name="Children">
......;
</Property>
</Property>
<Property value="TkResourceDescriptorData.xml">
<Property name="Id" value="_HEAD_DIPLO" />
<Property name="Name" value="_Head_Diplo" />
<Property name="ReferencePaths" />
<Property name="Chance" value="0" />
<Property name="Children">
......;
</Property>
</Property>
<Property value="TkResourceDescriptorData.xml">
<Property name="Id" value="_HEAD_HIPPO" />
<Property name="Name" value="_Head_Hippo" />
<Property name="ReferencePaths" />
<Property name="Chance" value="0" />
<Property name="Children">
......;
</Property>
</Property>
<Property value="TkResourceDescriptorData.xml">
<Property name="Id" value="_HEAD_RHINO" />
<Property name="Name" value="_Head_Rhino" />
<Property name="ReferencePaths" />
<Property name="Chance" value="0" />
<Property name="Children">
......;
</Property>
</Property>
<Property value="TkResourceDescriptorData.xml">
<Property name="Id" value="_HEAD_STEG" />
<Property name="Name" value="_Head_Steg" />
<Property name="ReferencePaths" />
<Property name="Chance" value="0" />
<Property name="Children">
.....;
</Property>
</Property>

Процедура така: існує основна частина, яка вирішує, чим вона буде, в нашому прикладі це _HEAD_. Зазвичай частини, назви яких починаються з нижнього підкреслення, означають, що вони відносяться до групи дескрипторів і тільки одна з них буде обрана для фінальної моделі. Як ви бачите, це частина визначена в списку TkResourceDescriptorList. Його елементи містять властивість «is invalid», дочірні елементи якого є кандидатами на вибір. Далі потрібно просто вибрати один з дочірніх елементів властивості is invalid. Так, наприклад, вибирається модель голови. Після вибору цієї конкретної моделі голови є ще одна властивість «is invalid», що має власний список можливих варіантів, і з нього знову потрібно вибрати один. І так далі.

Після виконання цих операцій для всіх елементів у файлі descriptor.mbin ми в результаті отримаємо набір вибраних частин, з якого створюється унікальна повна модель.


Приклад SHARKRIG


Винищувач, експортований з програми перегляду моделей No man's Model Viewer


Варти

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

Найважливішим у цій процедурі є спосіб вибору частини. Якщо уважно подивитися на представлений вище XML-код, можна побачити, що в кожній частині є властивість «Chance», але досить у багатьох частин його значення дорівнює 0. Думаю, що справжні ймовірності вибору частин або визначаються движком при виконанні гри, або встановлюються в інших файлах параметрів гри. У моїй програмі перегляду моделей я рандомизировал вибір. Всі частини мають однакову ймовірність вибору і це призводить до появи досить відмінних моделей.


Випадкова генерація істот на підставі моделі трицератопса


Процедурна генерація винищувачів (куби — це ненанесенные декалі)


Процедурна генерація посадочних шлюпок


Процедурна генерація SHARKRIG

Я провів в грі близько 70 годин, і за весь цей час я ні разу не зустрів істоту, схожу на диплодока. Це означає, що або движок містить помилку і ці частини не вибираються (в чому я сумніваюся), або ймовірність вибору цих частин настільки мала, що вони надзвичайно рідко з'являються в грі. Безліч обговорень (в основному розгніваних) зачіпало відсутній у грі контент і контент, присутній тільки в ігрових трейлерах, а також схожі теми. Я не можу судити про роботу ігри або про геймплейних можливості, але судячи з вивченого мною кількістю моделей істот, у грі існує КУПА контенту, який через рішень движка (?) з'являється в грі не дуже часто (або не з'являється зовсім). По-моєму, процедурно генеруються моделі диплодоков в 10 разів краще статичних, і якби розробники захотіли, вони змогли б змусити движок завантажувати статичні моделі (і, зрозуміло, весь контент з трейлера) в будь-який момент, тому, добре це чи погано, але це, швидше за все, дизайнерське рішення.


Модель диплодоків з трейлера на E3

Ось як працює основна частина процедурної генерації моделей. Це дуже елегантна, розумна процедура, тому що художники можуть дуже зручно додавати новий контент для процедурної генерації. Насправді, при додаванні кожної нової частини число комбінацій збільшується експоненціально (якщо ця частина доступна на всіх шляхах дерева). Наскільки я знаю, у розробників над моделями працювало два чи три художники. Вибухає мозок факт про процедурної генерації: якщо б вони подвоїли кількість людей, працюючих тільки над цією частиною роботи, ігровий контент (стосується істот) був би в сотні разів більше. І цей факт сам по собі доводить можливості і потенціал ігрового движка NMS.

Текстури
Текстура — це ще один складний аспект моделей NMS. Як я згадав у розділі «Геометрія», всі частини сіток визначаються у файлах SCENE.MBIN. Елементи цих файлів виглядають приблизно ось так:

<Property value="TkSceneNodeData.xml">
<Property name="Name" value="_Head_Tri" />
<Property name="Type" value="MESH" />
<Property name="Transform" value="TkTransformData.xml">
<Property name="TransX" value="0" />
<Property name="TransY" value="0" />
<Property name="TransZ" value="0" />
<Property name="RotX" value="0" />
<Property name="RotY" value="0" />
<Property name="RotZ" value="0" />
<Property name="ScaleX" value="1" />
<Property name="ScaleY" value="1" />
<Property name="ScaleZ" value="1" />
</Property>
<Property name="Attributes">
<Property value="TkSceneNodeAttributeData.xml">
<Property name="Name" value="BATCHSTART" />
<Property name="AltID" value="" />
<Property name="Value" value="19140" />
</Property>
<Property value="TkSceneNodeAttributeData.xml">
<Property name="Name" value="BATCHCOUNT" />
<Property name="AltID" value="" />
<Property name="Value" value="5772" />
</Property>
<Property value="TkSceneNodeAttributeData.xml">
<Property name="Name" value="VERTRSTART" />
<Property name="AltID" value="" />
<Property name="Value" value="3777" />
</Property>
<Property value="TkSceneNodeAttributeData.xml">
<Property name="Name" value="VERTREND" />
<Property name="AltID" value="" />
<Property name="Value" value="4894" />
</Property>
<Property value="TkSceneNodeAttributeData.xml">
<Property name="Name" value="FIRSTSKINMAT" />
<Property name="AltID" value="" />
<Property name="Value" value="97" />
</Property>
<Property value="TkSceneNodeAttributeData.xml">
<Property name="Name" value="LASTSKINMAT" />
<Property name="AltID" value="" />
<Property name="Value" value="124" />
</Property>
<Property value="TkSceneNodeAttributeData.xml">
<Property name="Name" value="MATERIAL" />
<Property name="AltID" value="" />
<Property name="Value" value="MODELS\PLANETS\CREATURES\TRICERATOPSRIG\TRICERATOPS\HEADTRIMAT.MATERIAL.MBIN" />
</Property>
</Property>
<Property name="Children">

Як ви бачите, тут є кілька атрибутів, які я зараз описувати не буду, і поговорю тільки про останньому. Він визначає матеріал, використовуваний для сітки. Як видно, цей сайт посилається на файл матеріалу, який потрібно використовувати. Давайте розглянемо цей файл матеріалу:

<?xml version="1.0" encoding="utf-8"?>
<Data template="TkMaterialData">
<Property name="Name" value="DiploHeadMat" />
<Property name="Class" value="Opaque" />
<Property name="TransparencyLayerID" value="0" />
<Property name="CastShadow" value="True" />
<Property name="DisableZTest" value="False" />
<Property name="Link" value="" />
<Property name="Shader" value="SHADERS/UBERSHADER.SHADER.BIN" />
<Property name="Flags">
...
</Property>
<Property name="Uniforms">
...
</Property>
<Property name="Samplers">
<Property value="TkMaterialSampler.xml">
<Property name="Name" value="gDiffuseMap" />
<Property name="Map" value="TEXTURES/PLANETS/CREATURES/TRICERATOPSRIG/DIPLOHEAD.DDS" />
<Property name="IsCube" value="False" />
<Property name="UseCompression" value="True" />
<Property name="UseMipMaps" value="True" />
<Property name="IsSRGB" value="True" />
<Property name="MaterialAlternativeId" value="" />
<Property name="TextureAddressMode" value="Wrap" />
<Property name="TextureFilterMode" value="Трилінійні" />
<Property name="Anisotropy" value="0" />
</Property>
<Property value="TkMaterialSampler.xml">
<Property name="Name" value="gMasksMap" />
<Property name="Map" value="TEXTURES/PLANETS/CREATURES/TRICERATOPSRIG/DIPLOHEAD.MASKS.DDS" />
<Property name="IsCube" value="False" />
<Property name="UseCompression" value="True" />
<Property name="UseMipMaps" value="True" />
<Property name="IsSRGB" value="False" />
<Property name="MaterialAlternativeId" value="" />
<Property name="TextureAddressMode" value="Wrap" />
<Property name="TextureFilterMode" value="Трилінійні" />
<Property name="Anisotropy" value="0" />
</Property>
<Property value="TkMaterialSampler.xml">
<Property name="Name" value="gNormalMap" />
<Property name="Map" value="TEXTURES/PLANETS/CREATURES/TRICERATOPSRIG/DIPLOHEAD.BASE.NORMAL.DDS" />
<Property name="IsCube" value="False" />
<Property name="UseCompression" value="True" />
<Property name="UseMipMaps" value="True" />
<Property name="IsSRGB" value="False" />
<Property name="MaterialAlternativeId" value="" />
<Property name="TextureAddressMode" value="Wrap" />
<Property name="TextureFilterMode" value="Трилінійні" />
<Property name="Anisotropy" value="0" />
</Property>
</Property>
</Data>

Важлива частина файлів матеріалів — розділ «Samplers». Очевидно, що в цьому розділі визначаються текстури, використовувані в частині моделі. І ось що цікаво: для статичних моделей всі текстури є дуже якісними текстурами, які без всяких проблем можна використовувати безпосередньо на моделях. Але якщо сітка використовується для процедурно генерується моделі, правильною є тільки текстура нормалей. Дифузна текстура, яка містить всю колірну інформацію про частини, являє собою порожню білу текстуру.

Спочатку я вирішив, що всі кольори і текстури теж вибираються при виконанні гри, але насправді це не так. Ці файли текстур завжди супроводжуються файлами ".TEXTURE.MBIN", які, як можна здогадатися, працюють в точності як файли дескрипторів моделей. Вони визначають спосіб комбінування текстур для створення фінальної дифузної текстури моделі. Художники гри не тільки створили різні частини моделей, але і намалювали безліч різних текстур для кожної частини. Тому, проходячи по цьому файлу таким же чином, як і за дескриптора файлу, можна обчислити фінальну дифузну текстуру процедурно генерується моделі. Більше того: навіть якщо дві моделі однакові з точки зору геометрії, завдяки процедурної генерації текстур вони можуть мати абсолютно різні кольору, мітки, форми і т. д.


Приклад текстури з плямами

Деталі текстури при процедурної генерації можуть дуже сильно відрізнятися. Схоже, що текстури створюються пошарово. Я покажу приклад складання процедурно генерується текстури істоти. Зазвичай нижнім шаром служить базова текстура додає основний колір і відтінок моделі (імена таких текстур закінчуються на .BASE.DDS). На наступному шарі знаходиться текстура підчерев'я (.UNDERBELLY.DDS), яка додає деталей на череві тварини. Потім йде ще один шар, додає більше деталей на випадкових ділянках моделі (.UNDERLAYER.X.DDS). Потім йдуть мітки (.MARKINGS.X.DDS), що визначають найбільш помітні деталі шкіри моделі. На наступному шарі знову знаходяться деталі шкіри, розташовані поверх відмітин (.SKIN.DDS), а на останньому шарі накладається ще одна текстура (TOP.X.DDS), що додає деталей на окремі частини моделі.

Схоже, що максимальна кількість шарів в процедурних текстурах одно 8 (зазвичай використовується 5 або 6). Очевидно, що існує безліч текстур, які потрібно змішати разом. Тому всі текстури супроводжуються відповідною текстурою маски, що містить необхідну інформацію про альфа-каналі, щоб змішування було як можна більш точним. Найчастіше текстури також супроводжуються відповідною картою нормалей, яка створює деталі на кожній частині.

Але всього цього хаосу з текстурами недостатньо, навіть з усіма смешиваниями фінальна текстура не має правильної розмальовки. І розробники придумали ще один геніальний технічний трюк. Вони хотіли, щоб істоти мали колір, що відповідає кольорам середовища, і реалізували це в грі з допомогою палітр. Я не впевнений на 100%, як вони працюють в грі, але опишу, що вони роблять на мою думку. Я застосував свій спосіб реалізації у програмі перегляду, і, судячи з усього, він досить точний.


FURPALETTE.DDS


PAINTPALETTE.DDS

Отже, в процесі створення планети (або створення зоряної системи) вибираються певні кольори, які будуть використані для живих істот всієї планети. Я кажу про вибір кольору, тому що в ігрових файлах є конкретні колірні палітри розміром 8×8 (в папці PCBANKS/TEXTURES/PALETTES). Ймовірно, ці панелі становлять різні форми. Це означає, що 64 кольори, що містяться на панелях, зазвичай об'єднуються в групи по 4 або 8 кольорів. Тому коли гра створює середовище планети, вона вибирає з цих груп, які будуть використані пізніше. Ці групи легко визначити, дивлячись на панелі, тому що вони насправді є градієнтом двох граничних квітів.

Індексування в обраній групі виконується з інформацією, що міститься у файлі .texture.mbin file. Опис текстури в таких файлах виглядає наступним чином:

<Property value="TkProceduralTexture.xml">
<Property name="Name" value="GRADIENT" />
<Property name="Palette" value="TkPaletteTexture.xml">
<Property name="Palette" value="Fur" />
<Property name="ColourAlt" value="Alternative1" />
</Property>
<Property name="Probability" value="1" />
<Property name="TextureGameplayUse" value="IgnoreName" />
<Property name="OverrideAverageColour" value="False" />
<Property name="AverageColour" value="Colour.xml">
<Property name="R" value="0" />
<Property name="G" value="0" />
<Property name="B" value="0" />
<Property name="A" value="0" />
</Property>
<Property name="Diffuse" value="TEXTURES/PLANETS/CREATURES/TRICERATOPSRIG/ALIENDIPLO.MARKINGS.GRADIENT.DDS" />
<Property name="Normal" value="TEXTURES/PLANETS/CREATURES/TRICERATOPSRIG/ALIENDIPLO.MARKINGS.GRADIENT.NORMAL.DDS" />
<Property name="Mask" value="TEXTURES/PLANETS/CREATURES/TRICERATOPSRIG/ALIENDIPLO.MARKINGS.GRADIENT.MASKS.DDS" />
</Property>

Я знову не буду говорити про те, що роблять інші опції. Нас хвилює тільки опис властивості «Palette». З інформації у цьому властивості ми можемо дізнатися, який колір нам потрібно вибрати для частини. У нашому випадку видно, що вимагається індекс панелі «Fur» (хутро) (яка, як ми бачили раніше, складається з груп по 4 кольори), та у вибраній групі нам потрібний колір «Alternative1». Ось як індексуються кольорів в палітрах. Ці значення властивості «ColourAlt» можуть бути рівними «Primary», «Alternative1», «Alternative2», «Alternative3» і т. д. Означає, primary буде першим цвітом у групі, alternative1 — другим і т. д. Тут я теж не на 100% впевнений, але я використовую панелі так, і це логічно, виходячи з принципу груп кольорів.

Отже, у нас є один базовий колір для певної текстури, що ж нам з ним робити? Треба просто помножити його на колір текстури. Зазвичай ігрові текстури мають блакитнуватий колір, який виглядає нейтральним. Після множення на колір панелі текстура отримує потрібний насичений колір.

Повторюю, ця операція виконується для кожної окремої текстури, що наноситься на модель. Всього їх може бути 8, ми отримуємо їх, комбінуємо з відповідними кольорами палітри, змішуємо шари знизу доверху і наносимо на модель.

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

Анімації

Скелетна анімація моделі трицератопса


Цикл анімації ходьби астронавта


Анімація повільної ходьби процедурно згенерованої моделі Spiderrig

Чесно кажучи, я не досліджував анімації так докладно, як геометрію і текстури. Все що я зробив (і це було не так просто, як здається :P) — виконав парсинг анімацій і успішно відтворив їх у моїй програмі перегляду моделей. У цій категорії також є безліч цікавих і унікальних деталей.

По-перше, скелети моделей визначаються у файлах «SCENE.MBIN». Вони являють собою ієрархічну систему шарнірів, до якої за допомогою скиннінгу вершин прикріплюються частини моделей. У цьому немає нічого дивного. Цікаво те, що, як я згадав у розділі «Геометрія» у файлі SCENE.MBIN є безліч частин сіток. Тому для керування анімацією і рухом всіх цих частин призначена система шарнірів впливає на частини сцени.

Анімації працюють точно так само, вони анимируют весь скелет, навіть якщо не всі шарніри використовуються для фінальної згенерованої моделі. На перший погляд це виглядає безглуздою тратою ресурсів. Насправді єдиною тратою є тут парсинг всього файлу анімації. При виконанні гри файли MBIN SCENE і GEOMETRY надають достатньо інформації, щоб завантажувати графічний процесор тільки дані, необхідні для кожної конкретної моделі.

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

Висновки
Я спробував пояснити, як працює гра, наскільки я зрозумів її після трьох тижнів роботи. Я зосередився на генеруванні істот, але ті ж принципи застосовуються і до інших аспектів (кораблі, NPC, будівлі, рослини). Коли я починав працювати з файлами, всі були захоплені грою, шукали новизни і різноманітності. Минули тижні, і гру почали вважати монотонною. Питання в наступному: коштувала процедурна генерація використання в NMS?

Однозначної відповіді на це питання немає.

Як розробник ПЗ і реверс-розробник відеоігор я відповідаю: так, безумовно коштувала. З технічної точки зору я ніколи не бачив ігрових механік, схожих на механіку NMS, і я сумніваюся, що побачу в нових іграх, які використовують технологію процедурної генерації. Тому що ніхто не буде намагатися створювати вигадані світи з таким рівнем випадковості. Технічно No man's Sky стала справжнім скарбом, і кожен, хто намагається заперечувати це, просто бреше собі, або не знає про те, як працює гра (або не цікавиться цим). Ігровий движок має дуже великий потенціал, і я постійно думаю про те, якою могла стати гра, якби движок був у руках великий ігровий студії. Навіть з урахуванням обмеженості ресурсів мені все одно подобається різноманіття істот, яке я бачу в грі (і я вважаю, що за допомогою більш тонкого налаштування ми можемо вичавити навіть більше з наявних ресурсів).

Мої почуття як гравця суперечливі. Хоча це і не мій стиль гри, але з самого замовлення No man's Sky я знав, що це буде гра, у якій я зможу просто розслабитися. Вивчати навколишнє середовище, рослини і тварин. Спочатку всі вони здаються однаковими, але придивившись, ми побачимо в більшості з них відмінності. Може бути, відрізняються тільки текстури, але вони різні: це може бути маленький ріг на голові істоти, або різні плями, чи відрізняється деталь корабля. Контент у грі (навіть геймплейний, який розробники могли б реалізувати, якби хотіли), не можна сказати, що його немає. Все, що ми отримуємо — це результат надзвичайно гарною процедури генерації. Фактично, контент, створюваний двигуном NMS для системи з 2-3 планет, набагато перевершує ресурси, які можна бачити, наприклад в ARK. Зрозуміло, ніякі істоти не будуть повністю ідеальними, як динозаври в ARK, але в цьому і полягає їх принадність. Саме движок може створювати розкішних і величних створінь, і в той же час — найбільш незрозумілих тварин, які були в комп'ютерних іграх. Ось чому я купив цю гру, і чому я люблю її. Я живу заради тих моментів, коли після дослідження різної стомлюючої нісенітниці я раптово приземляюся на найкрасивішу планету, яку коли-небудь бачив. Повторюся, я не порівнюю елементи RPG або можливості геймплея. Я кажу тільки про процедурному контенті. Це не означає, що гра не могла бути краще. Я вірю, що могла, і чекаю, що розробники її поліпшать.

З іншого боку, якщо ви не налаштовані на розслаблення, терплячість і увагу до деталей, гра не варто покупки, і вся процедурна генерація для вас буде простою тратою ресурсів. Це не шутер, де за вами постійно полюють і ви постійно перебуваєте в напрузі. Розробники чітко дають це зрозуміти. Для тих, хто вибрав такий стиль гри, все буде виглядати однаковим. Навіть якщо б контент з трейлера створювався в грі, і на кожній другій планеті була пишна рослинність, динозаври і піщані хробаки, гра все одно набридла б вам. Після третьої зоряної системи вам здалося б все однаковим, тому що ви не уважно придивлялися. Не можна звинувачувати гру або розробникам за те, що ви не займаєтеся дослідженнями в грі про дослідження. Крім того, процедурна генерація ніколи не була і не стане способом створення гідного контенту «з нуля». Принаймні, не в найближчому майбутньому. Не можна просто написати математичний вираз і створити нову тварину. Таке згодиться для рельєфу, рослин, каменів або кораблів (при цьому текстурування все одно буде під великим питанням), але для живих рухомих об'єктів, таких як істоти або NPC все стає настільки складним, що це практично неможливо. (Зрозуміло, якщо б це було можливо, у розробників не було причин не зробити цього, адже вони вже зробили подібне з іншими об'єктами.) Тому якщо ви очікуєте через кожні п'ять кроків бачити нового інопланетянина, то вибачте, це проблема ваших очікувань, а не розробників. Якщо і є спосіб створення такого контенту, то це саме спосіб движка NMS.

Зрештою, після всіх моїх досліджень я знаю, що в грі є досить контенту, щоб принаймні створювати все по-новому на кожній планеті, так що я не можу звинувачувати гру або движок. Я можу звинуватити налаштування і конфігурування движка. Ще я можу звинуватить прокляті багатоплатформений релізи та видавця. Я впевнений на 10000000000000000000%, що розробники були змушені поспішати при випуску гри. Гра, яку ми отримали, далека від завершення, і навіть не наближається на 80% до можливостей, які передбачені движком. Після вивчення файлів мені це абсолютно ясно. Вона ближче до технічної демці, а не до гри. Спроба запхати однаковий контент на PC і PS4 просто розтерзав гру, а прагнення змусити її працювати на слабких машинах ще більше знизило якість. Особисто я чекаю оновлень, і їх повинно бути багато. Я можу пробачити безліч помилок Hello Games при релізі ігри, завищену вартість, брак зв'язку з споживачами, навіть відсутність багатьох можливостей (наприклад, багатокористувацького режиму, на який, чесно кажучи, мені начхати). Але навіть з урахуванням плутанини і напруги перед релізом я не можу вибачити того, що вони не змогли повністю показати, на що здатен двигун з правильною конфігурацією. Моддери зараз занурюються в нетрі файлів і намагаються знайти способи створення тим же самим движком більш багатого і різноманітного контенту. І найчастіше у них це виходить, тому що движок може забезпечувати набагато більш якісну гру. Всі ці опції повинні бути доступними будь-якому гравцеві, а не тільки моддерам. Очевидно, розробники вирішили не давати гравцям такої можливості, щоб всі вони перебували в однаковій всесвіту і могли мати спільні точки маршруту, істот і планети. Але вони повинні були залишити таку можливість. Зробити упор на одиночній грі і показати всім гравцям, на що здатен двигун.

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

Ще до того, як движок гри стане настільки прекрасним…
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.