Deep dive into Level Design: створення рухомих інтерактивних об’єктів для мап Mech Arena

Привіт, мене звати Данііл, я левел-дизайнер у Plarium. Я працюю на проєкті Mech Arena — це динамічний PvP-шутер, орієнтований на командну взаємодію. Десятки мехів і видів зброї, різні ігрові режими й понад 45 мап для боїв з особливим ігровим процесом на кожній.

Ми постійно прагнемо покращувати ігровий досвід користувачів, урізноманітнювати його. Саме через це виникла ідея додавати на мапи Mech Arena інтерактивні рухомі об’єкти. Це робить бої динамічнішими, а враження гравців захопливішими. У статті я поетапно розкажу й покажу, як ми втілили ідею в життя. Поділюся викликами, з якими довелося зіштовхнутися, і рішеннями, що ми вибрали.

Як працює Level Design у Mech Arena

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

Дизайн мапи має бути «читабельним» для користувачів. Це важливо, бо він допомагає скеровувати гравців, шукати безпечні та небезпечні зони, додаткові шляхи й позиції для оборони та атаки. Звісно, мапа має бути гарно збалансована. У Mech Arena я враховую багато чинників, включно з метриками, зброєю та ігровими механіками, саме в контексті арена-боїв між реальними гравцями.

П’ять етапів, що допомагають мені відбалансувати мапу та зробити її зрозумілою для гравця

1. Визначення цілі мапи або того, який новий ігровий досвід варто створити для гравців. Я планую розмір мапи та бій, що хочу бачити. Це буде велика відкрита мапа для дальнього бою з використанням артилерії та джавелінів чи невелика мапа close range під дробовики й високу динаміку? Або щось між ними, як-от середня дистанція та вертикальний лейаут. Будь-який вибір не означає, що я нехтуватиму якимись мехами чи видами зброї. Усе має працювати добре, але для кожної мапи передбачені свої фаворити. Це потрібно для того, щоб гравці отримували різноманітний досвід від бою і їм було цікаво експериментувати зі збиранням мехів і зброї.

Розміри готових грейбоксів мап Mech Arena «Сталість», «Контроль» та «Артефакт Х»

2. Вибір візуальної теми для сету мап. У Mech Arena в одному сеті зазвичай три мапи. З концепт-художником ми генеруємо ідеї та збираємо дошку з референсами. Маючи декілька варіантів, затверджуємо один із них разом із Game Director та Art Director.

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

Фінальний вигляд мап із різних сетів: «Сталість», «Димова труба» та «Лабораторія»

3. Блокінг (грейбокс-версія мапи). Етап, на якому починається креативний процес реалізації ідей: створення мапи «із чистого аркуша», закладання фундаменту й бачення фінальної графіки в прямокутних сірих кубиках. Хтось починає з концепту на папері, начерків простенької схеми майбутньої локації. Я ж віддаю перевагу працювати одразу в 3D-просторі з великими формами, закладати лендмарки й точку інтересу (POI), а потім уже занурюватися в деталізацію. Як на мене, це найзручніший підхід, бо він дає змогу одразу протестувати мапу, побігати нею, відчути її.

Готовий грейбокс мапи «Сингулярність»

4. Балансування мапи. Під час створення мап у Mech Arena я враховую різноманітні чинники. У грі понад 25 мехів, що мають різну швидкість, розмір, абілки, HP. А також понад 90 видів зброї з різною далекобійністю, ефектами та принципом роботи (пошкодження за радіусом, самонаведення, артилерія). Через це важливо ретельно продумувати точки спавну та різні ігрові ситуації наперед, бути уважним до метрик, розбивати мапу на зони, направляти гравця формою, кольором, світлом, лендмарками, точками інтересу (POI). Як правило, для всіх режимів, крім FFA, ми створюємо симетричні мапи. Це дає змогу уникнути додаткових балансних ризиків і зекономити час.

Готова грейбокс-версія мапи «Димова труба»

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

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

Тестування грейбокс-версії мапи «Сингулярність»

До того ж я займаюся менеджментом напрямку Level Design, аналітикою, підтримкою на всіх етапах пайплайну та постійними імпрувами ігрового досвіду гравців. Один із цих імпрувів — додавання інтерактивних рухомих об’єктів на мапи, про що я і розповім далі.

TDM-мапи 5×5 та рухомі інтерактивні об’єкти для них

Ідея зробити об’єкти, з якими гравці можуть взаємодіяти, виникла давно. Ми навіть частково реалізували це на мапі «Димова труба». У центрі над точкою захоплення ми розмістили два укриття, які повільно обертаються навколо отвору. Нічого складного: простенька анімація для групи об’єктів, використання компонента NavMesh Obstacle з увімкненим Carve (для динамічної зміни NavMesh). Поки що жодної інтерактивності, але є нюанс — синхронізація цих об’єктів між гравцями.

Уся геометрія мапи розміщується локально в гравця на девайсі. Щоб сервер розумів положення рухомих об’єктів у конкретний момент, його треба про це сповістити. Для цього ми створили скрипт Movable World Object View. Якщо його додати до параметрів рухомого об’єкта, то розсинхронізація руху такого об’єкта між гравцями зникає. Здавалося б, круто, тепер можна робити різні види рухомих каверів, закривати й відкривати проходи, створювати пастки. Але під час роботи над мапами «Сингулярність», «Рівновага» та «Сталість» виникли нові виклики й усе стало ще цікавіше.

Демонстрація роботи рухомих об’єктів на мапі «Димова труба»

Робота над мапами «Сингулярність», «Рівновага» та «Сталість»

Левел-дизайн мап та основна ідея

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

  • об’єкти з вертикальним рухом: знищують мехів та викидні абілки. Під «викидними» я маю на увазі абілки, які мех може встановити безпосередньо на мапі, наприклад міни чи турелі;
  • об’єкти з горизонтальним рухом: не завдають шкоди меху (не завжди), але можуть деактивувати викидні абілки.

Ідея вертикальних небезпечних об’єктів також була зумовлена технічними нюансами. Щоб реалізувати платформу, на якій мех може рухатися вгору чи вниз (меха дуже трясе), нам треба було змінити Character Controller та витратити багато часу на зміну коду й тестування. А часу було обмаль.

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

Демонстрація технічної проблеми вертикального й горизонтального руху об’єктів

Я вирішив зробити дві просторі мапи й одну більш закриту. Кожна мапа має власний темп, динаміку й фаворитний рендж зброї, про які я розповім далі.

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

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

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

Визначення візуальної теми

Ми з концепт-художником побрейнштормили та знайшли референси. Виник намір створити небезпечний і загадковий паралельний простір, який ніхто не досліджував. Тож вирішили розвинути тему таємничого «Артефакту Х» з однієї з попередніх мап і розповісти історію про те, звідки він і яку небезпеку чи користь несе жителям всесвіту Mech Arena.

Бої на мапі «Артефакт Х» відбуваються на космічному кораблі

Ми надихалися Control, Astral Chain і деякими елементами Death Stranding. Чому саме ці ігри? За нашою концепцією це мав бути паралельний всесвіт, де панує хаос, але зі своїм порядком.

Можливо, звучить трохи парадоксально, але ж це фантастика. Людські закони фізики не притаманні цьому середовищу: тут немає жодної органіки, лише кубічні блоки з невідомої людству гірської породи, які підпорядковуються потужній і небезпечній енергетичній матерії. У Control та Astral Chain схожа концепція — паралельний простір, прямокутні форми оточення й густа атмосфера.

Деякі референси

Розроблення грейбокс-версії мапи

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

Початкові концепти

Наступним моїм кроком стало створення першого лейауту. Ним став грейбокс мапи «Сингулярність».

Мапа «Сингулярність»

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

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

Початковий спавн (грейбокс)
Початковий спавн (фінальний вигляд)

Я розбив рухомі об’єкти за кольорами, щоб мені й учасникам плейтесту було простіше їх розуміти на грейбокс-версії мапи:

  • об’єкти з горизонтальним рухом — зелені;
  • об’єкти з вертикальним рухом — фіолетові. Вони мають вставки з Emissive-матеріалом, який загоряється червоним, коли об’єкт стає небезпечним для меха та гравця. Але вже на наступній мапі із сету я перетворю цю індикацію на більш інформативну.

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

Індикація небезпеки рухомого об’єкта

Для реалізації руху я створив окрему Legacy-анімацію для кожного об’єкта й використовував першу версію скрипту Movable World Object View, щоб під час плейтесту рух об’єктів коректно синхронізувався між усіма гравцями.

🗺️ Рухомі об’єкти мапи «Сингулярність»

a) Рухомі стіни, що виїздять знизу й утворюють укриття для базового спавну для кожної команди. Їхня основна мета — показати гравцеві локацію, а потім зробити базовий спавн безпечним.

Рухомі стіни на базових точках команд

b) Центральні рухомі кавери, що безперервно обертаються навколо своєї осі. Їхня роль на мапі — створювати укриття, відкривати/закривати простріли для обох команд у центральній частині мапи, де пролягає найпряміший шлях до бази супротивника. Крім створення анімації руху та скрипту на синхронізацію, важливо враховувати поведінку ботів із такими об’єктами.

Центральні рухомі кавери та робота NavMesh Obstacle

На проєкті Mech Arena ми використовуємо два типи навігації для AI:

  • стандартна навігація від Unity або NavMesh;
  • внутрішнє розроблення нашої команди — Astar-навігація, алгоритм пошуку шляху для ботів, який безпосередньо впливає на патерн їхньої поведінки під час бою.

На момент створення грейбоксу я працював тільки з NavMesh, а для Astar-навігації треба було ще провести певні тести. Щоб динамічно розривати навігацію в місцях, де об’єкт буде рухатися в певний момент, я використовував компонент NavMesh Obstacle з увімкненим Curve. Навігація коректно розриватиметься в місцях руху, і боти це враховуватимуть.

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

Вертикальні небезпечні рухомі об’єкти

Щоб навчити об’єкт знищувати мехів та викидні абілки, я використав Box Colliders, дуже близько підігнані під розмір самих об’єктів, і додавав на них наш внутрішній скрипт Kill Zone View із параметром Everything. Роботу цих колайдерів (KillBox) можна побачити на гіфці вище: вони зафарбовуються в червоний колір, коли стають небезпечними. Увімкнення та вимкнення групи KillBox я додавав безпосередньо в анімацію руху.

Скрипт Kill Zone View

Трохи розкажу про роботу скрипту Kill Zone View. У своєму початковому стані скрипт робив колайдер небезпечним тільки для мехів. Я використовував його для створення небезпечних зон на мапі. Але протягом тестування виникла потреба модифікувати скрипт, тому тепер ми можемо вибирати, який саме тип об’єктів має знищуватися:

  • None — жодного впливу на колайдер;
  • Everything — робить колайдер небезпечним для мехів і викидних абілок;
  • Actors — робить колайдер небезпечним тільки для мехів;
  • World Objects — робить колайдер небезпечним тільки для викидних абілок.

Кольорова схема параметрів скрипту Kill Zone View

Робота колайдера з параметром Everything

Робота колайдера з параметром Actors

Робота колайдера з параметром World Objects

d) Горизонтальні рухомі об’єкти знищують викидні абілки, проте ніяк не впливають на мехів, хіба що можуть трохи відштовхнути гравця під час руху. Тут використовувався скрипт Kill Zone View із параметром World Objects. Головне завдання цих об’єктів — функція динамічного кавера, за яким гравець може тимчасово сховатися, та утворення/прибирання прострілів із різних позицій для обох команд. Оскільки ці кавери трохи заїжджають на центральну лінію вогню, тут, за аналогією з пунктом «b», треба використовувати компонент NavMesh Obstacle з увімкненим Curve, щоб динамічно змінювати NavMesh.

Горизонтальний рухомий об’єкт

Мапа «Сингулярність» має центральну симетрію. Рухомі об’єкти в пунктах « та « також розташовані симетрично. Отже, розташувавши об’єкти й налаштувавши їм таймінги, я отримав єдину систему рухомих об’єктів для цієї мапи, які працюють як злагоджений механізм. Саме цього я і прагнув.

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

Перші візуальні концепти мапи «Сингулярність»

🗺️ Рухомі об’єкти мапи «Рівновага»

На мапі «Рівновага» я використовував осьову симетрію, тому й рухомі об’єкти розташовані для кожної команди дзеркально. Я використовував уже закладені на попередній мапі принципи, але є одна цікава зона, для якої знадобилося більше часу на баланс і полірування. Детальніше про неї — у пункті «d».

а) Горизонтальний рухомий об’єкт, який під час руху своїми гранями по осі X знищує мехів і викидні абілки (параметр Everything). Оскільки він перебуває в ігровому полі, використовується NavMesh Obstacle для динамічної зміни NavMesh.

Горизонтальний рухомий об’єкт, параметр Everything

b) Горизонтальні рухомі об’єкти, що знищують тільки викидні абілки, тобто мають параметр World Objects. Тут також використовується компонент NavMesh Obstacle.

Горизонтальні рухомі об’єкти, параметр World Object

c) Вертикальні рухомі колони з параметром Everything. На грейбоксі вони були небезпечними тільки під час руху вгору, але після плейтесту я вирішив зробити небезпечним і їхній рух униз.

Вертикальні рухомі об’єкти, параметр Everything

d) Вертикальні рухомі платформи, які під час руху мають параметр Everything, а коли зупиняються, утворюють проходи над проваллям як для першого, так і для другого ярусу мапи. Це найскладніший у реалізації комплекс рухомих елементів, адже треба було ретельно відбалансувати таймінги й налаштувати навігацію для ботів. Щоб зробити навігацію для першого та другого ярусів, де будуть рухатися платформи, я створив тимчасову групу геометрії та встановив наш внутрішній Tag «NavMeshHelper». Тепер ця група геометрії сама вмикатиметься та вимикатиметься під час запікання навігації, мені не доведеться робити це вручну.

Тимчасова група геометрії для запікання NavMesh та Astar

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

Я створив окремі додаткові об’єкти з компонентом NavMesh Obstacle, як уже колись робив. Але раніше цей компонент був безпосередньо частиною рухомої геометрії. Такі собі невидимі куби, нижній і верхній, прикріплені до кожної платформи окремо. Для них вимкнено Mesh Renderer і Collider, відпрацьовує тільки NavMesh Obstacle з увімкненим Curve.

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

Робота «невидимих кубів» із навігацією під час руху

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

  • синій — безпечно;
  • жовтий — приготуйся;
  • червоний — небезпека.

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

Після роботи над мапою «Рівновага» стало зрозуміло, що знову створювати такий складний комплекс рухомих об’єктів, як платформи з пункту «d», буде занадто ризиковано для дедлайнів. Тому під час роботи над останньою мапою в цьому сеті я зосередився на простіших у реалізації рухомих об’єктах.

🗺️ Рухомі об’єкти мапи «Сталість»

На мапі «Сталість» я працював із менш ризиковими видами рухомих об’єктів. Проте це моя улюблена мапа в сеті.

а) Рухомий вертикальний об’єкт, який є небезпечним (параметр Everything) під час руху. Він відкриває та закриває позицію/прохід біля центру мапи в певні проміжки часу.

Вертикальний рухомий об’єкт (параметр Everything)

b) Рухомі горизонтальні об’єкти, які мають параметр World Objects, тобто знищують тільки викидні абілки мехів. Центральний об’єкт відіграє роль рухомого кавера, від якого можна грати й рухатися разом із ним. Боковий об’єкт відкриває та закриває прохід у певні проміжки часу.

Горизонтальні рухомі об’єкти (параметр World Object)

Мапа має симетрію відносно центру на 180°, тому й рухомі об’єкти розташовані симетрично для кожної команди.

Внутрішнє тестування грейбоксів і передавання команді Environment

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

  • Team — приналежність до команди А чи В. Або це взагалі універсальна точка для режиму Free For All;
  • Type — Base (основний спавн, що використовується на старті раунду), Base Additive (один із двох додаткових спавнів, що разом із Base доступні для респавну гравця після його смерті в грі) або MVP-точка (використовується на екрані MVP після завершення гри);
  • Spawnpoint ID — ідентифікатор, який присвоюється групі або одній точці спавну (у випадку з FFA).

Приклад точок спавну для команди В, мапа «Сталість»

Загалом усі потрібні мені інструменти є у двох внутрішніх тулах нашої команди розроблення. Це Level Editor і Level Design Tool. Завдяки їм я можу створювати точки спавну, MVP-точку та Weapon Ruler, що допомагає відобразити ренджі та траєкторію будь-якої зброї в грі. Також можу створити мінімапу, запекти навігації NavMesh та Astar, задати режим гри мапі тощо.

Розставивши точки спавну й задавши режим мапі (у нас це TDM 5×5), я запікаю навігацію для ботів і коригую місця, де її не має бути або де вона запеклася некоректно. Завершивши, я зберігаю дані в Level Preset. Це файл типу .json, який містить усю інформацію про мапу: назву сцени, режим, точки спавну, ефекти postprocess, додатковий бандл із бекграундом сцени (ми використовуємо систему бандлів) і ще багато інших важливих моментів. Готовий Level Preset я завантажую на тестовий сервер безпосередньо з меню Level Editor, що дуже зручно.

Ще один важливий етап — налаштування світла на мапі. Світло — потужний інструмент для керування увагою гравця та підсилення потрібних акцентів. Для грейбоксу, як правило, я налаштовую світло так, щоб мапа добре читалася, підсвічую бойові позиції та проходи. І загалом роблю блокінг приємним на вигляд, адже нам ще на ньому грати. До запеченого світла я іноді додаю легенький Fog, особливо якщо закладаю якісь дальні елементи Far за межами мапи. Іноді ще налаштовую Skybox, щоб додати мапі атмосфери.

Хоч це грейбокс-версія мапи, я також слідкую за оптимізацією, щоб увесь мій «безлад» запустився на плейтесті. Тому я додатково запікаю Occlusion culling. І за допомогою інструменту Physics Debug перевіряю, чи не загубився десь зайвий невидимий колайдер посеред відкритої місцевості й чи все нормально з іншими колайдерами на мапі.

Робота інструменту Physics Debug

Закінчивши налаштування та перевірки, я завантажую дані у свою гілку (використовую Sourcetree), з якої потім буду збирати тестові білди. Для збирання ми використовуємо автоматизовану систему Jenkins, вона дає змогу зручно та швидко збирати тестові білди й оновлювати дані серверів.

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

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

Допрацювання механіки рухомих об’єктів та Astar-навігації

Передавши лейаути в роботу Environment Team, я перейшов до розв’язання проблем із рухомими об’єктами, які виявили після плейтестів.

a) Сервер не розуміє, що таке колайдер зі скриптом Kill Zone View. Це означає, що коли гравець покине бій, а його мех взаємодіятиме з небезпечним об’єктом, нічого не станеться, меха не знищить.

Нерозуміння небезпечного колайдера сервером, мапа «Рівновага»

b) Створення можливості вибирати тип колайдера для скрипту Kill Zone View (None, Everything, Actors, World Objects). Як я писав вище, це потрібно для того, щоб колайдер міг окремо впливати на різні типи об’єктів. Також скрипт не реагував на викидні абілки, замість того щоб знищити умовну міну: небезпечний об’єкт рухався далі, а міна перебувала на місці чи навіть висіла в повітрі.

Скрипт Kill Zone View не реагує на викидні абілки, мапа «Рівновага»

c) Розривання Astar-навігації, коли об’єкт починає рух. Як я зазначав, цей тип навігації — наше внутрішнє розроблення, що має вигляд каркаса із сітки, яка покриває підлогу. Саме Astar-навігація впливає на поведінку ботів. Тому ми й мали створити інструмент, що дає змогу динамічно змінювати вузли цієї навігації.

Astar-навігація, мапа «Сингулярність»

d) Зміна принципів дії абілки меха Redeemer. Навичка цього спритного малюка дає йому змогу подорожувати в часі й повертатися на свою позицію на 10 секунд назад. Якщо поруч були рухомі об’єкти, мех міг повернутися в те місце, де такий об’єкт розташований, і застрягти в ньому. Через це виникла потреба навчити його самознищуватися.

Взаємодія рухомого об’єкта та абілки меха Redeemer, мапа «Рівновага»

Ще перед роботою над мапами я обговорив усі свої ідеї з Unity-розробниками, тож ми вже були готові до фіксу проблем із цього списку. Щоб нам із розробниками та QA Team було зручно працювати, я створив лейаут з усіма типами рухомих об’єктів, які використані на мапах. Отже, нам не довелося перемикатися між різними сценами й можна було робити все безпечно в одному місці, без ризику зламати щось з уже готового.

Лейаут для тестування рухомих об’єктів

Я вже розповідав про те, як ми покращили роботу скрипту Kill Zone View. Ми також навчили сервер розуміти, коли цей скрипт із колайдером впливає на меха чи викидну абілку, тому я зосереджуся на інших рішеннях.

Отже, щоб розв’язати проблеми а та b — викидних абілок, що висять у повітрі, і мехів, що не реагують на небезпечний колайдер (у гравців, які покинули бій), — було внесено багато змін у скрипт Movable World Object View. Він відповідає за синхронізацію всіх рухомих об’єктів на мапі. Я не зупинятимуся на цьому пункті, адже пояснення потягне на ще одну статтю. Те саме можу сказати про абілку меха Redeemer. Якщо коротко, механіка повернення в часі була допрацьована й тепер мех, потрапляючи всередину будь-якого об’єкта, самознищується.

Але я детальніше розповім про розв’язання ледь не найскладнішої проблеми, а саме про роботу з Astar-навігацією. Я розкажу, як ми реалізували динамічний вплив на неї. Astar-навігація нагадує триангульовану сітку 3D Mesh і має свої Vertex (вузли), у яких з’єднуються грані цієї сітки. Щоб від’єднати потрібні сектори сітки, треба навчитися вмикати й вимикати вузли в певні проміжки часу. Для цього в сцені створюється умовний куб. Його потрібно розташувати так, щоб він покрив усі вузли в зоні, де треба змінювати навігацію.

Далі я вимикаю компонент MeshRenderer і видаляю BoxCollider, адже це має бути невидимий об’єкт, який не впливає на гравця. Потім додаю наш внутрішній скрипт GraphUpdateScene, створений для того, щоб розв’язувати завдання з вимиканням і вмиканням вузлів Astar-навігації.

Самостійно такий об’єкт нічого не робить. Щоб він запрацював, треба зробити його частиною рухомого об’єкта. Тобто потрібно дати зрозумілий неймінг (наприклад, AstarGraphUpdater), додати в статичну підгрупу до батьківської групи рухомого об’єкта, унести до поля Element (пункт Graph Updaters) у скрипті Movable World Object View, розміщеного на батьківській групі рухомого об’єкта. Це має такий вигляд:

Вплив об’єкта Graph Update на вузли Astar-навігації під час руху стіни

Червоні вузли й сітка навколо них означають, що ця зона відключена. Боти розцінюватимуть її як закриту для проходження, допоки сітка знову не стане синьою.

Таких об’єктів може бути декілька для одного рухомого об’єкта. У скрипті Movable World Object View до поля Element можна додати куби й призначити особистий номер.

Призначення номерів елементам Graph Update у полях Element0 та Element1 відповідно

На прикладі видно, що елемент AstarGraphUpdaterRight розміщений у полі Element0, а AstarGraphUpdaterLeft — у полі Element1. Це номери 0 та 1 відповідно. Тепер я маю налаштовані елементи. Залишилося зробити так, щоб вони синхронно працювали з рухом об’єкта. Для цього ми використовуємо систему івентів для анімації.

Є три типи взаємопов’язаних івентів, які мають розміщуватися послідовно:

  1. AnimEventOnPrepare: попереджає статичний об’єкт GraphUpdate, до якого рухатиметься анімований об’єкт (відповідно до нумерації). Указуємо номер об’єкта, який має активуватися.
  2. AnimEventOnMove: рухомий анімований об’єкт почав рух. Активується і поточний (в AnimEventOnPrepare), і наступний статичний (в AnimEventOnStop) об’єкт GraphUpdate, відповідно до нумерації. Тобто активовані обидва. Указуємо номер, об’єкта, який має активуватися.
  3. AnimEventOnStop: зупинка анімованого рухомого об’єкта, деактивація попереднього статичного GraphUpdate-об’єкта. Активованим залишається наступний об’єкт, який став поточним, відповідно до нумерації. Указуємо номер об’єкта, що має деактивуватися.

Коли статичний GraphUpdate-об’єкт активований, він вимикає вузли Astar-навігації (робить зону unwalkable для ботів). А коли деактивований, то вмикає знову. Тоді зона стає walkable.

Щоб GraphUpdate-об’єкт знав, коли й у якому порядку йому треба вмикати та вимикати вузли навігації, потрібно коректно вказати наші івенти на анімації та присвоїти їм номери відповідно до того, у які поля Element я поклав GraphUpdate-об’єкти. У нашому випадку це AstarGraphUpdaterRight = Element0 із номером 0 і AstarGraphUpdaterLeft = Element1 із номером 1.

Рухома стіна з попереднього скриншоту має декілька різних статичних позицій, коли закінчується рух. Тобто в нас є два коридори — А та Б. Рухома стіна, яка певний час закриває коридор А, потім рухається й після зупинки закриває коридор Б, а також одночасно відкриває коридор А. І навпаки. І так нескінченно. Отже, там, де розташована стіна, вимикаються вузли Astar-навігації. Тож івенти мають такий вигляд: AnimEventOnPrepare=0 >>> AnimEventOnMove=0 >>> AnimEventOnStop=1. На цьому етапі стіна закінчила рух і змінила свою позицію, закривши правий коридор і відкривши лівий.

Іншими словами, AnimEventOnPrepare повідомляє, що стіна скоро почне рух у позицію 0 (AstarGraphUpdaterRight). Далі починається рух і AnimEventOnMove активує позицію 0 (водночас позиція 1 усе ще буде активна). Тепер вузли Astar-навігації вимкнені в місцях зі статичними об’єктами AstarGraphUpdaterRight (0) та AstarGraphUpdaterLeft (1). Адже пам’ятаємо, що активований AstarGraphUpdater = вимкнені вузли Astar-навігації.

Потім стіна зупиняється й відпрацьовує AnimEventOnStop, що деактивує позицію 1 (AstarGraphUpdaterLeft, зона стає walkable) та залишає активною позицію 0 (AstarGraphUpdaterRight, зона стає unwalkable).

Тепер стіна має повернутися на початкову позицію, поїхати назад, тому нам треба поставити івентам номери відповідно до руху, інвертувавши їх: AnimEventOnPrepare=1 >>> AnimEventOnMove=1 >>> AnimEventOnStop=0. Це й буде кінцем і початком зацикленої анімації. Розумію, виглядає заплутано. Сподіваюся, гіфки нижче допоможуть розібратися.

Візуалізація роботи AnimEvent та GraphUpdater

Цифри 1 та 0 показують номери відповідних GraphUpdater-об’єктів:

  • червоний: вузли навігації вимкнено, об’єкт активовано;
  • синій: вузли навігації увімкнено, об’єкт деактивовано;
  • жовтий: підготуватися до активації об’єкта.

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

Візуалізація роботи AnimEvent та GraphUpdater та вплив на Astar-навігацію

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

Головне — пам’ятати, що тепер наша платформа (умовно стіна) деактивує GraphUpdater-об’єкт, коли закінчується рух, і вмикає вузли Astar-навігації. Отже, за такої самої нумерації івентів (AnimEventOnPrepare=0 >>> AnimEventOnMove=0 >>> AnimEventOnStop=1 >>> AnimEventOnPrepare=1 >>> AnimEventOnMove=1 >>> AnimEventOnStop=0) я розташовую GraphUpdater-об’єкти відповідно: AstarGraphUpdaterTop=Element0 і AstarGraphUpdaterBottom=Element1.

Розташування GraphUpdater-об’єктів для вертикальної платформи. Top деактивований — вузли навігації увімкнено, Bottom активований — вузли навігації вимкнено.

Візуалізація роботи AnimEvent і GraphUpdater та вплив на Astar-навігацію для вертикальної платформи

У майбутньому ми плануємо покращити цю систему та зробити її зручнішою.

Налаштування рухомих об’єктів на фінальних версіях мап

Як зазначалося вище, фінальною графікою займається команда Environment, а я займався механіками рухомих об’єктів і був на сапорті, коли в команди виникали питання з левел-дизайну мап. Команди Environment та Tech Art підготували ефекти й текстури для рухомих об’єктів, які ми попередньо затвердили, щоб я міг налаштувати візуальну індикацію. Отримавши від художників першу готову мапу «Сингулярність», я почав налаштування анімацій руху об’єктів та візуальних ефектів.

Візуальні ефекти мають виконувати роль індикації, попереджувати гравця про рух та небезпеку. На мапі «Сингулярність» усі рухомі об’єкти, які є небезпечними, мають «прожилки» в текстурі каменя. Ці прожилки від спокійного темного кольору нагріваються до яскраво-червоного й у такий спосіб сигналізують про майбутній рух об’єкта.

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

Індикація небезпечного рухомого об’єкта на мапі «Сингулярність»

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

Індикація безпечного рухомого об’єкта, «Сингулярність» — Final

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

Робота вертикальних платформ з Astar-навігацією та активація небезпечних колайдерів, мапа «Рівновага»

Робота вертикальних платформ із камери гравця, мапа «Рівновага»

Робота інших рухомих об’єктів із камери гравця, мапа «Рівновага»

Робота рухомих об’єктів у сцені, мапа «Сталість»

Робота рухомих об’єктів із камери гравця, мапа «Сталість»

Ми хотіли попередити гравця про небезпеку не тільки візуально, а й звуком. Тому я також працював над цим завданням разом з аудіопродюсером. Ідея була в тому, щоб у момент, коли небезпечний рухомий об’єкт покривається енергією, гравці чули її звук — тріщання. Це призвело до того, що скрипт Movable World Object View обріс новими можливостями й полями для додавання звуку.

Доданий звук у скрипт Movable World Object View, мапа «Сингулярність»

Звук небезпечного рухомого об’єкта, мапа «Сингулярність»

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

Не обійшлося без фіксів, але переважно то були дрібниці, які ми швидко виправили.

На наступному етапі я передав відео та білди нашим Games Writers, щоб узгодити фінальні назви мап і перейменувати Level Presets із Dev-назв на Prod-назви. І, як приємне закінчення роботи, надав інформацію для команди Motion Design, що створила чудові трейлери до релізу нових мап «Сингулярність», «Рівновага» й «Сталість».

Висновок

Коментарі до трейлерів на YouTube, відгуки в Discord та дані аналітики показали, що гравцям сподобалися нові мапи. Фідбек ком’юніті завжди мотивує нас покращувати проєкт, експериментувати та реалізовувати нові ідеї. Тому я впевнений, що в майбутньому ми з командою продовжимо розвивати підхід із рухомими інтерактивними об’єктами.

Дякую, що дочитали цей лонгрід до кінця. Маю надію, що вам було не тільки цікаво, а й корисно. Буду радий почути ваші запитання й думки в коментарях!

Підписуйтеся на Telegram-канал @gamedev_dou, щоб не пропустити найважливіші статті і новини

👍ПодобаєтьсяСподобалось17
До обраногоВ обраному6
LinkedIn


Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

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

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

З мап подобалися лише перші. Більшість нових, включаючи Димову Трубу, не так зачіпали. Особисто у тій самій трубі викликала фрустрацію вхідна зона по центру на першому поверсі труби, де можна засісти удвох та на ізі кемперити. Взагалі у трубі не зрозумів прикол з хазардами у вигляді калюж з кислотою. Занадто гніває гравців як мене :)

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

Сподобалися мапи під арену типу 2×2. Але опісля декількох останніх оновлень та агресивного навʼязування донату закинув грати.

1. Заголовок статті повідомляє уважному читачеві, на чому саме зосереджена ця стаття. Але це все ще левел дизайн. Якщо ти не знав, левел дизайнери не займаються виключно створенням грейбоксів мап.
2. Назвати розробку ігрової механіки налаштуванням сцени, викликає в мене дуже позитивні емоції 😁.
3. «До того ж, балансування мап мехарени бажає кращого, так як на більшості з усіх мап домінують саме 2-3 види зброї, вони супер імбові.»
— В цьому реченні ти суперечиш сам собі. Поганий баланс мап (які симетричні, всі в рівних умовах) чи все ж 2-3 види імбової зброї?
4. «Можливо ситуацію трошки виправили мехи з більш сильними щитами яких додали пізніше. Але то вже гуляє баланс механік, а не мап.»
— Знову ж таки, тут вже кажеш баланс механік є проблемою.
4. Я розумію, що деякі мої роботи можуть не подобатись комусь із гравців. Адже все залежить від стилю гри кожної окремої людини. І це нормально давати критику, для мене це цінна інформація. Але жодну свою ідею я не вважаю тупою.

Дякую за фідбек!

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

Без токсичності не можна було обійтися? Чи це така фішка у людей з пларіуму?)

Назвати розробку ігрової механіки налаштуванням сцени, викликає в мене дуже позитивні емоції 😁.

Ок. Багато не зміниться від цього, назвати розробку ігрової механіки левел дизайном 😄

«До того ж, балансування мап мехарени бажає кращого, так як на більшості з усіх мап домінують саме 2-3 види зброї, вони супер імбові.»
— В цьому реченні ти суперечиш сам собі. Поганий баланс мап (які симетричні, всі в рівних умовах) чи все ж 2-3 види імбової зброї?

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

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

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

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

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

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

Дуже крута статття. Хоч я й не левел дизайнер, але читати цікаво🔥

Дякую! Мені дуже приємно чути, що було цікаво😊

Та з цієї статті можна цілий курс зробити! Потужно!
Дякую!

Підписатись на коментарі