Процедурна генерація рівнів для M. E. R. C. у Unity

image

Частина перша
Процедурна генерація рівнів — відмінний спосіб додати в гру більше контенту та несподіваних сценаріїв. Для сюжетних місій M. E. R. C. ми хотіли створити великий набір зроблених вручну рівнів, але усвідомлювали, що нашій невеликій інді-команді не вистачить часу або ресурсів на виготовлення контенту для такої великої гри. Крім того, ми прагнули додати випадковість і підвищити реіграбельность гри. Процедурна генерація рівнів дозволила нам створити великий, нескінченно мінливий світ, який ми не змогли б отримати, ладу окремі рівні вручну. Використання процедурної генерації дозволяє додати більше контенту та поліпшити ігровий процес.

Що таке M. E. R. C.? M. E. R. C. — це тактичний симулятор загону в реальному часі з видом зверху. Гравець одночасно керує загоном з чотирьох найманців у антиутопическом світі Неотопии, віддає накази і активує особливі вміння. Кожен найманець загону має власні особливі бойові, технічні та хакерські навички, які необхідно використовувати у місіях. Візуально M. E. R. C. нагадує стиль «Біжить по лезу»: темні дощові нетрі і дахи міста з безліччю звивистих вулиць і неоновим освітленням. Сюжет полягає в війні могутніх корпорацій за контроль над Неотопией. Загін наймають для виконання різних завдань корпорацій, таких як викрадення вчених конкурентів або вбивство співробітників-перебіжчиків. Кожна одержана місія впливає на відносини з різними корпораціями і в результаті змінює ігровий світ. Враховуючи все це, давайте розглянемо вимоги до процедурної генерації рівнів.

image

Вимоги до рівнів
Рівні являють собою лабіринт з міських нетрів і дахів, але щоб у них було цікаво грати, вони повинні мати особливу структуру. Для створення великих рівнів місій ми вирішили збирати їх з невеликих фрагментів. Завдяки цьому ми змогли б виготовити вручну цікаві та «багаторазові» фрагменти, додати процедурну випадковість і надати кожному рівню відчуття зробленого вручну. Для цього ми визначили, що процедурний рівень повинен:

  • містити один основний маршрут
  • містити 1-3 тупикових шляхи для цілей і збирання видобутку
  • містити 1-3 коротких шляху, використовуваних як альтернативні маршрути
  • генерувати випадкові об'єкти оформлення в кожному фрагменті рівня
  • генерувати ворогів на підставі «графіка темпу»
  • генерувати різні типи і рівні ворогів на підставі складності місії
  • працювати з системою NavMesh Unity
  • бути детермінованим і генерувати абсолютно однакові рівні для спільної гри по мережі
Ці вимоги підібрані з урахуванням нашого геймплея, світу та запланованої тривалості місій. В інших іграх будуть власні вимог до системи процедурних рівнів. Ми хотіли, щоб місії можна було проходити всього за десять хвилин і в два рази повільніше при ретельному дослідженні рівня. Це означало, що важливим параметром стала невелика варіативність у довжинах шляхів.

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

Генерування маршруту рівня
Перша проблема системи процедурних рівнів полягає в генеруванні цікавого основного маршруту, що містить тупики і короткі шляху. Ми знайшли рішення в доповіді Зака Эйкмана (Zach Aikman) з Unite 2014 про генеруванні рівнів гри Galak-Z студією 17-BIT (повний доповідь можна подивитися тут).

Доповідь Зака дуже цікавий, і я раджу його подивитися. Розповім про нього коротко: для генерування основного 2D-маршруту ми використовували модифікований алгоритм кривий Гільберта. Він створює цікавий і унікальний звивистий маршрут, що ідеально підходить в якості основи для наших рівнів. Розробники Galak-Z використовували його для маршруту в двомірному вигляді збоку, ми з його допомогою створювали двовимірний вид зверху. Уявіть, що на ілюстрації нижче показана схема вулиць нашої гри у вигляді зверху.

image
(ілюстрація з доповіді про Galak-Z)

Після генерування основного маршруту потрібно оцінити всі можливі осередки карти для створення коротких шляхів, і випадковим чином вибрати частину з них. Короткий шлях не дозволяє скоротити переміщення по всій карті, а просто зрізає частину основного маршруту, наприклад, щоб уникнути деяких ворогів. Ми додали в код обмеження, щоб короткі шляхи не були занадто довгими і частими. При додаванні цих коротких шляхів у фрагменти рівнів ми часто блокували їх дверима, які можна «хакнути», або іншими перешкодами, які вимагали яких-небудь дій гравця. Це додає більше варіативності в основний маршрут рівня і надає ще один спосіб перевірити навички гравця.



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



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

Після завершення генерування повного маршруту з короткими шляхами і тупиками ми перетворимо його в список завантажуваних фрагментів рівнів. Кожен фрагмент рівня — це сцена Unity, тому кожній сцені ми дали назву по шаблону, який визначає її конфігурацію. Згенерувавши рівень, ми перетворюємо кожну клітинку карти назва сцени, відповідне шаблоном. Шаблон містить тему фрагмента, з'єднання і позначення варіації. Наприклад, за шаблоном <тема>_<з'єднання основного маршруту>_<з'єднання короткого шляху>_<з'єднання глухого кута>_<варіація> фрагмент рівня може мати назву сцени «slums_03_-1_-1_A».

Тема — це візуальний стиль фрагментів рівнів. Всі фрагменти рівнів однієї теми повинні легко з'єднуватися з будь-яким іншим фрагментом такої ж теми. Наприклад, всі фрагменти рівнів теми «slums» (нетрі) повинні логічно і графічно поєднуватися один з одним в точках сполук. Ми також створили тему «rooftops» (дахи будинків), в якій замість з'єднаних один з одним вулиць дахи будівель з'єднані скатами і настилами. Зазвичай всі фрагменти однієї теми мають однаковий розмір. Наші фрагменти в середньому мають розмір 40x40 одиниць.

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



Наприклад, фрагмент рівня з позначенням з'єднання основного маршруту «03» має з'єднання внизу (0) і праворуч (3). Відмітка з'єднання основного шляху завжди має порядок збільшення (тобто «03», а не «30»). Важливо пам'ятати, що при складанні фрагментів рівнів з'єднання необов'язково повинні вибудовуватися абсолютно рівно. Додавши деяких сполук нерівності, ми збільшимо варіативність і зменшимо плавність з'єднання фрагментів. Однак з'єднання все одно повинні бути вирівняні один відносно одного, щоб шляхи обов'язково зістиковувалися.

Варіації дозволяють дизайнеру рівнів створювати різні версії одного фрагмента рівня. Наприклад, подивіться на дві варіації «A» і «B» з'єднання основного маршруту «01» без короткого шляху. При генеруванні рівня система випадково вибирає одну з варіацій кожного фрагмента рівня, забезпечуючи більше візуальне розмаїття.

image

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

image

Буду радий більш детально обговорити цю тему і з задоволенням прийму будь-які пропозиції. Зі мною можна зв'язатися Twitter.

У другій частині статті «Процедурна генерація рівнів для M. E. R. C. у Unity» ми обговоримо вирішені нами проблеми освітлення і NavMesh, а також процес генерування персонажів у місії на підставі темпу. Чекайте продовження!
Джерело: Хабрахабр

0 коментарів

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