Игра Кухня о 3 технических вызовах, связанных с созданием Камня Безумия

В начале этого года компания The Game Kitchen выпустила The Stone of Madness, тактическую RPG, в которой игроки помогают пяти заключенным сбежать из инквизиторской тюрьмы. В этом гостевом посте три разработчика из студии делятся тем, как они справлялись с проблемами рендеринга, пользовательского интерфейса и тестирования в процессе разработки.
Мы The Game Kitchen, и мы недавно выпустили The Stone of Madness на ПК и консолях. Мы хотим поделиться некоторыми из самых насущных проблем, с которыми мы столкнулись в процессе разработки нашего последнего проекта, рассматривая их с технической точки зрения и с практическими примерами. В этой совместной статье наша команда программистов разбирает ключевые решения, которые мы реализовали в Unity для оптимизации как производительности, так и эффективности разработки.
Сначала Адриан де ла Торре (графический программист) объяснит, как мы разработали и отобразили художественный процесс игры, чтобы достичь его отличительного визуального стиля.
Далее Альберто Мартин (программист пользовательского интерфейса) расскажет, как мы использовали Noesis для оптимизации разработки пользовательского интерфейса, улучшив рабочий процесс с помощью улучшений UX на основе отзывов пользователей.
Наконец, Рауль Мартон (программист игрового процесса) продемонстрирует, как мы внешне организовали и автоматизировали тесты для сложных игровых действий на сервере, обеспечивая обработку множества крайних случаев без нарушения интеграции.
Делая безумие привлекательным Взгляд на пользовательский рендер-пайплайн
Адриан де ла Торре, графический программист, The Game Kitchen
Камень Безумия сочетает 2D визуальные эффекты с 3D игровыми механиками, что представляет собой уникальную техническую задачу. Хотя игроки видят 2D мир, основные системы игры работают в трехмерном пространстве, создавая отличительную двойственность в ее дизайне.
Чтобы справиться с этой задачей, наша команда разработчиков создала пользовательский процесс рендеринга, который эффективно соединяет информацию о 3D игровом процессе и 2D визуальное представление. Это решение реализует несколько проходов рендеринга и специализированные техники для поддержания визуальной согласованности, сохраняя при этом задуманную глубину игрового процесса, что позволяет бесшовно переводить 3D-элементы в характерный 2D-арт-стиль игры.
В "Камне безумия" есть два основных сценария, которые способствуют созданию кадра.
Первый сценарий, который мы называем Сценарием Прокси, состоит из геометрических примитивов, которые рассчитывают освещение финального кадра.

Второй сценарий - это сценарий Canvas, который состоит из спрайтов, соответствующих форме и положению геометрии Proxy. Канвас организован в слоях, чтобы смоделировать 3D-пространство и достичь правильной сортировки по оси Z с движущимися игровыми элементами.
Следующий раздел описывает каждый шаг в нашем графическом конвейере для рендеринга кадров.
1. Конус зрения
Когда конус зрения или игровая способность активируется, это инициирует первый шаг в цепочке. Мы устанавливаем камеру на точке зрения NPC, чтобы отобразить глубину прокси в его поле зрения.

Затем, в другой текстуре рендеринга, камера выводит градиент расстояния от точки начала игрока в канале B, который используется для эффектов области навыков.

Используя текстуру рендеринга PoV NPC, камера конуса зрения рендерит конус поверх предыдущей текстуры в каналах R и G с информацией об препятствиях и расстоянии.

Финальный проход отображает звуковые волны в альфа-канале.

Это финальная текстура, созданная на этом этапе, которая будет использована на этапе Камера Холста для рендеринга спрайтов сцены.

2. ID камеры рендеринга холста
Каждый прокси в нашем проекте имеет связанный идентификатор рендеринга (значение с плавающей запятой). Прокси и связанный с ним спрайт имеют один и тот же идентификатор рендеринга. На этом этапе мы отображаем значение float Render ID в текстуру рендеринга.

На следующем этапе мы используем эту текстуру, чтобы сопоставить информацию о освещении, рассчитанную в прокси-сценарии, с спрайтами в сценарии Canvas.
3. Осв
Освещение в нашей игре состоит из:
- Запеченное освещение Естественные источники света, которые остаются постоянно активными, такие как внешнее освещение.
- Смешанное освещение Статические огни в сцене, которые можно включать и выключать, такие как свечи.
- Свет в реальном времени: Свет, который перемещается по сцене и может быть включен и выключен (мы реализовали это только в одном экземпляре, масляной лампе Альфредо)
Используя текстуру RenderID, мы создаем текстуру рендеринга, содержащую информацию о освещении из прокси-сцены.

4. Камера Canvas
После создания всех текстур рендеринга камера начинает рендерить спрайты с информацией о освещении, зонах действия навыков, конусах видимости и звуковых волнах.
5. Постобработка
Цветокоррекция, виньетирование и другие эффекты применяются на этапе постобработки.
6. UI
Наконец, пользовательский интерфейс наложен.
Безумие в HUD: Ускорение процессов пользовательского интерфейса
Альберто Мартин, программист пользовательского интерфейса, The Game Kitchen
Окончательная версия The Stone of Madness включает более 50 пользовательских интерфейсов. Причина этого числа в том, что в этой игре много данных, которые нужно показать пользователю. Наша работа над пользовательским интерфейсом занимала очень много времени, особенно учитывая, насколько маленькой была команда в начале, поэтому мы постоянно оптимизировали наши процессы, чтобы гарантировать, что добиваемся хороших результатов за как можно меньшее время.
Наша работа по пользовательскому интерфейсу охватывала весь проект, поэтому было важно, чтобы наши дизайнеры UI/UX четко понимали все функции, которые нам нужно было реализовать. Чтобы обеспечить хорошее взаимодействие с пользователем и сделать игру увлекательной, мы внимательно следили за тем, чтобы поддерживать открытую линию связи между командами программистов и дизайнеров.
Чтобы создать лучшие версии всех наших компонентов пользовательского интерфейса, нам нужно было устранить барьеры между нашими техническими командами и командами креативщиков/исследователей, чтобы все активно участвовали в разработке игры. Вот как мы подошли к этому двухчастному рабочему процессу.
Роль исследований и креатива в дизайне пользовательского интерфейса
Наши дизайнеры UI/UX отвечают за определение того, как элементы интерфейса будут выглядеть в финальной игре, и за обеспечение удовлетворительного пользовательского опыта. С учетом этого они начали с создания каждого элемента с минимальной технической нагрузкой и его проверки с потенциальными пользователями. Этот процесс выглядел так:
- Реквизиты: Понимание потребностей игрока и составление списка потребностей игры и целей пользователя
- Расследование Смотрим на другие игры, чтобы увидеть, как они справлялись с аналогичными проблемами.
- Каркасные модели Работа над схемами и структурой (на данный момент нет финального искусства)
- Макет: На этом этапе мы монтируем почти полностью разработанный интерфейс с ранее созданными элементами (кнопками, прокрутками, рамками и т. д.), что позволяет нам итеративно работать без особых усилий.
- Прототип: Мы создаем прототип в Figma, используя наш макет, симулируя взаимодействия с геймпадами и клавиатурой/мышью, чтобы показать, как это будет работать в реальной среде.
- Тест пользователя: Используя наш ранее созданный прототип, мы инициируем пользовательское тестирование, подтверждая потребности и цели, которые мы определили на Шаге 1.
- Этап итерации: Если тест пользователя соответствует ожиданиям, он передается на технические процессы, делаются дополнительные итерации или проводятся дальнейшие тестирования, если это удобно.
Техническая реализация пользовательского интерфейса
Как уже упоминалось ранее, количество элементов пользовательского интерфейса в "Камне безумия" огромно. Разработка движка пользовательского интерфейса дорогостоящая, поэтому нам нужно было использовать фреймворк, который легко изучать и который имеет хорошие инструменты и рабочие процессы. После оценки ряда промежуточного ПО мы выбрали Noesis GUI, который следует паттерну Model-View-ViewModel (MVVM).
Мы выбрали Noesis, потому что он основан на WPF (Windows Presentation Framework) и следует модели MVVM таким образом, что мы можем повторно использовать большую часть документации, библиографии, записей на форумах и так далее для устранения большинства проблем. Эта структура существует уже довольно долго – с момента ее первого выпуска прошло 18 лет – и знакома большому количеству разработчиков пользовательского интерфейса, что дает нашей студии возможность нанимать из сравнительно более широкого пула талантов для реализации интерфейсов и инструментов для наших проектов. Еще одна важная вещь о Noesis заключается в том, что мы можем использовать те же инструменты из WPF.
С помощью XAML наша команда дизайнеров интерфейсов занималась разработкой макета и доработкой всех элементов с минимальным техническим участием. Благодаря подходу MVVM наши технические UI-программисты могли сосредоточиться на функциональности и предоставлять поддержку креативным командам в определенных областях, когда это было необходимо.
Тестирование (или как не сойти с ума, создавая игру с системным дизайном)
Рауль Мартон, программист игрового процесса, Teku Studios
Игровой процесс в "Камне безумия" основан на трех основных столпах: Игровые навыки, ИИ NPC и взаимодействия в сценах. Каждая из этих трех систем фундаментально переплетена, что экспоненциально увеличивает количество ситуаций, которые игрок должен контролировать, – и количество сценариев, которые нам нужно протестировать.
Как только мы начали проект, мы поняли, что традиционная система контроля качества будет недостаточной. Просто было слишком много сценариев, которые зависели от взаимодействия нескольких элементов друг с другом определенным образом, создавая неконтролируемую ситуацию. Более того, эти ситуации могут возникнуть в промежутке времени, который слишком мал для комфортного тестирования командой контроля качества.
Чтобы решить эти проблемы, мы создали набор автоматических тестов. Идея заключалась в том, что все возможные сценарии/ситуации, которые могут возникнуть у нашей команды разработчиков в отношении конкретной системы, могут быть учтены и автоматически протестированы гораздо более эффективно в смоделированной игровой среде.
Чтобы привести пример, один из главных персонажей "Камня безумия", Амелия Экспозито, обладает способностью карманника. При реализации этого навыка мы инициировали серию тестов, чтобы убедиться:
- Основное функционирование навыка было правильным: При краже у NPC открывалась мини-игра по карманной краже, и игра приостанавливалась до её завершения.
- Менее распространенные ситуации также охватываются: Если вы попытаетесь украсть у NPC, пока за вами наблюдает другой NPC (например, стражник), или если NPC убегает, действие невозможно.

Создание интеграционного теста
Каждый интеграционный тест, который мы создали, требовал настройки на основе следующих требований:
1. Сцена, специально подготовленная для создания этой конкретной ситуации
Чтобы протестировать навык карманника, мы создали сцену с двумя охранниками и одним игроком. Мы расположили каждого персонажа так, чтобы они смотрели в нужном направлении для точного тестирования ситуации (помните, игрок не может использовать карманные кражи, если он находится в поле зрения охранника).
Кроме того, сцена должна включать только минимально необходимые компоненты для тестирования сценария, так как лишние элементы могут добавить шум в измерение. Вот почему в нашей примерной сцене нет HUD, системы ручного ввода, звуковых эффектов и так далее.
- Этот шаг требует, чтобы структура игры была хорошо разделена на компоненты, что может потребовать некоторых усилий, но, когда это будет достигнуто, оно того стоит! 😉
2. Тестовый код, способный принудительно создать ситуацию для тестирования
Многие из ситуаций, которые нам нужно было протестировать, могут быть сложными и трудоемкими для создания вручную и требуют отправки кода для инициации.
Например, если мы хотим создать тестовый сценарий, чтобы убедиться, что наши NPC никогда не наступают на мышеловки, если NPC не движется, цепочка инструкций будет следующей:
- Запустите сцену
- Подождите одну секунду
- Установите мышеловку под НПС
- Подожди еще секунду
- Прикажите НПС начать двигаться в любом направлении
Эта часть проекта очень чувствительна к любым изменениям в процессе разработки (зависит от таких факторов, как изменение спецификаций игры и различные неожиданные сценарии), поэтому критически важно, чтобы как тестовый код, так и полученная обратная связь были как можно более ясными.
Нет ничего хуже, чем тест, который не проходит, не давая никакой ясной информации о том, что на самом деле идет не так.
3. Надежный способ узнать, работает ли сценарий так, как задумано, или тест обнаружил ошибку в логике.
Автоматизированное тестирование все еще требует контроля. Увеличение числа тестов с большей специфичностью того, что тестируется, может стать трудным для мониторинга, или сценарии могут не тестироваться достаточно долго, чтобы быть статистически значимыми. Чтобы обойти эти проблемы, мы создали специальные инструменты.
Например, некоторые из наших тестов включали комбинированные взаимодействия между несколькими НПС в сцене. Чтобы правильно отслеживать эти случаи, мы создали систему для регистрации различных состояний ИИ, через которые проходят NPC во время теста.

Нам также нужен был хороший API, который бы дал нам возможность видеть текущее состояние игры (был ли НПС сбит в бессознательное состояние?) NPC вошел в маршрутизированное состояние? Сколько раз? Какой персонаж игрока был захвачен? И так далее).
4. Система, позволяющая быстро запускать все эти тесты:
В отличие от модульных тестов, автоматизированные тесты должны проводиться с запущенной игрой в реальном времени. Это может сделать выполнение этих тестов очень медленным.
В этих обстоятельствах мы можем воспользоваться тем фактом, что наша игра не использует стандартную систему обновлений Unity. Вместо этого все наши компоненты используют функцию Tick(), которая имитирует обновления Unity, но запускается контролируемым образом нашим игровым движком.
Это помогло нам достичь нескольких различных целей с нашими тестами:
- Во-первых, мы могли бы ускорить их выполнение с помощью принудительной функции, которая выполняет несколько фреймов кода для каждого фрейма игры.
- Во-вторых, поскольку эти тесты проводятся в реальном времени, они очень подвержены изменениям, вызванным частотой кадров на компьютере, выполняющем тестовый сценарий. Преобразуя их в контролируемую частоту кадров, мы избегаем этой вариации: Если тест проходит на одной машине, он пройдет на всех машинах, и наоборот.
И это будет результат.
Как безопасное тестирование помогает нам избежать сломанных сборок
С созданием этого набора тестов нам также нужно было реализовать защиту, которая автоматически прерывала бы слияние ветки, если в ней содержались бы ошибки. Чтобы это обеспечить, мы создаем автоматический скрипт слияния, который запускается каждый раз, когда изменения фиксируются в основной ветке проекта.
Этот скрипт гарантирует запуск всех этих тестов и мониторинг их результатов. Если какой-либо тест не проходит, он возвращает ошибку и прерывает слияние.
С этой системой мы можем избежать ситуаций, когда изменение в, казалось бы, изолированной системе ломает другие механизмы, с которыми она взаимодействует.
Спасибо The Game Kitchen за то, что поделились закулисным взглядом на разработку The Stone of Madness. Изучите больше игр, созданных с помощью Unity, на нашей странице кураторов Steam и получите больше информации от разработчиков на странице ресурсов Unity.