Процедурная генерация подземелий в Deusira

Всем привет! Это мой первый пост на пикабу в роли Game-разработчика и сегодня я расскажу о процедурной генерации в Deusira. Над этой игрой сейчас как раз и трудится наша небольшая команда. Жанр игры - First person roguelike с melee combat механикой. Так как в команде я играю роль программиста, на мои плечи была возложена задача реализовать процедурную генерацию подземелий и комнат в частности, про которую я и хочу рассказать. Я использую очень простые алгоритмы и правила, которые на выходе дают неплохой результат.

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Основные принципы генерации комнат

В основу генерации мы решили заложить следующий принцип: имеется n заранее смоделированных комнат, которые можно превратить в процедурные благодаря несложному алгоритму и определенным настройкам.


Как это работает: у нас есть набор моделей пола, стен, колонн, крыши и прочих элементов архитектуры. Сама комната представлена набором тайлов (буду называть их далее TileActor), каждый из которых может содержать один элемент архитектуры - ту же колонну (возможно вместе с ее разрушенными кусками), тайл пола, стены и т.д. В этом же TileActor содержится ряд настроек – сидов (seeds). Именно эти сиды отвечают за то, какой из static meshes (моделей) может появиться на месте TileActor, зависит ли выбор на этом актере от того, что было выбрано на другом, какая вероятность удаления куска архитектуры, какие куски несовместимы между собой и т.д. Соответственно задача алгоритма прочитать настройки на каждом актере и группе актеров, чтобы в итоге сделать выбор нужного элемента архитектуры из доступного списка. При этом учитывается вероятность появления определенного куска архитектуры (например разрушенная стена должна появляться только в 10% случаев).


Примерно такую рандомизацию можно получить на примере одной комнаты (свет еще не показываю - только архитектура):

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4
Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4
Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4
Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4
Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4
Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Следующий этап - установка факелов. Объединив колонны внутри комнаты в несколько групп (благодаря Torch Seed) имеем неплохие вариации для света: факела могут заспавниться на одной группе колонн или на нескольких, с одной или двух сторон, работающие или нет. Также я делаю простую проверку области где появится факел на коллизию с другими элементами архитектуры, перед тем как его спавнить.

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Генерация подземелья

Ну и самый главный этап - обьединить комнаты в готовый данж. Для этого я выбираю TileActor's стен, на месте которых можно разместить выход из комнаты, а также создаю блюпринт-прототип комнаты, в котором указан ее размер (через volume) и возможные координаты дверей (через billboads).

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Именно с этими прототипами и будет работать генератор подземелья на начальном этапе: он выбирает случайный прототип из списка и пытается разместить его таким образом, чтобы позиция будущей двери совпала с позицией двери одной из размещенных комнат, но чтобы при этом не было коллизии между текущей комнатой и существующими. По факту я имею массив точек, в которых можно поставить переход в другую комнату, а значит моя задача пройтись по этим точкам, постоянно вращая и изменяя позицию будущей комнаты до тех пор, пока она не займет свое законной место.

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4
Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4
Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Самое приятное для меня в этом простом алгоритме то, что комнаты могут размещаться не только на плоскости по соседству друг с другом, но и одна над другой, как на этом скриншоте.

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Для этого достаточно сделать в комнате несколько дверей и разместить возможные точки-выходы на разной высоте. Пока-что комнаты появляются впритык друг к другу, но в будущем это место займут комнаты-коридоры.

Теперь дело за малым - осталось только подгрузить наши комнаты в отведенные для них волюмы, провести рандомизацию элементов архитектуры и разместить факела.

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

В точках, которые были выбраны как проходы между комнатами появляются блюпринты-двери. Нужно не забыть установить для стены-арки над дверью такой же материал какой был у удаленной стены. Также я не забыл процедурно заменить "плинтус" на подходящий.

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Не забываем про аналогичную замену с другой стороны двери

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Добавим немного деталей, а именно траву, которая будет прорастать сквозь трещины в полу, между кирпичами а также в тех местах данжа, где находится грунтовый пол. Подобные тайлы-блюпринты пола можно довольно быстро разметить сплайнами, на которых будет расти будущая трава:

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Система генерации травы крайне простая: по готовому подземелью разбрасываются сферы со случайным размером. Если какой-то из участков сплайна попадает внутрь сферы, то мы можем разместить на нем foliage instance, при этом чем ближе трава к центру сферы – тем больше будет ее размер.

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4
Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Ну и напоследок еще пару деталей – как вы уже заметили, я размещаю в некоторых местах данжа туман и светлячки (particle).

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Итого, мы имеем данж, в котором есть комнаты с процедурным изменением архитектуры и света, а также с возможностью создания нескольких этажей. Ну а благодаря простоте этой системы генерации большая часть времени на загрузочном экране уходит на спавн актеров.

Процедурная генерация подземелий в Deusira Игры, Генерация подземелий, Roguelike, Гифка, Длиннопост, Gamedev, Разработка игр, Unreal Engine 4

Следующее над чем мы будем работать в ближайшем будущем - это одна из главных геймплейных механик (сражения с врагами в подземелье) и наполнение комнат элементами интерьера (генератор пропов).

Если эта маленькая статья окажется кому-то полезна или просто интересна, я с удовольствием буду писать о новых процедурных фичах, которые мы будем добавлять в проект по мере его развития.