что такое процедурная генерация
Процедурная генерация уровней
Работы по программированию, графике и звукам в некой новой игрухе закончены — остались только уровни. Лёгкая и приятная работа, но почему-то идёт с большим трудом. Возможно, сказывается общая усталость.
Думая, как бы упростить себе жизнь, в голову пришла идея о процедурной генерации. Ясное дело, её тоже надо будет писать, но как говорилось в одном известном произведении, «лучше день потерять, потом за пять минут долететь».
Внимание! Под катом много текста и «жирных» гифок.
Вводная
Уровни всё равно будут полироваться вручную, так что никаких особых требований по памяти, скорости работы и даже по качеству получаемых уровней нет.
Изначально я планировал, что генератор только накидает комнаты и двери, а вся дальнейшая доводка (сюжет, декорации и враги) будет проводиться в ручном режиме. Но на текущий момент я думаю, что генератор сможет гораздо больше. Тем не менее, ручная доводка всё равно останется — надо чтоб игроки чувствовали, что в уровни вложено хоть немного любви.
Я просмотрел свою базу знаний по геймдеву, и выписал в отдельный документ ссылки на статьи по процедурной генерации. Большинство, конечно, про генерацию классических лабиринтов или про генерацию рельефа (кстати, результаты очень впечатляющие), что не подходит для 3D-шутера. Но некоторые были близки к тому, что мне нужно (звёздочкой я отметил те, которые мне показались наиболее подходящими):
Я решил начать с последних двух — они просто реализуются, и дают хорошие результаты.
Структура генератора
На самом деле, к этой структуре я пришёл не сразу, а в процессе многочисленных рефакторингов и переписываний, но пишу про неё сразу, чтоб было понятно, что вообще происходит:
Есть ещё где-то 12 пунктов, но они пока не доделаны (когда доделаю, напишу про них отдельный пост).
Генерация изначальной геометрии: «BSP»
За основу был взят вот этот перевод. Я не уверен насколько то, что происходит в этом алгоритме близко к настоящему BSP, поэтому пишу «BSP» в кавычках.
Алгоритм достаточно прост. Изначально создаём прямоугольник, размером со всё игровое поле:
Затем делим его на рандомно на две части — либо горизонтально, либо вертикально. Где будет проходить линия разделения тоже выбираем случайным образом:
Рекурсивно проделываем тоже самое для новых прямоугольников:
И ещё раз и ещё раз, до некоторого предела:
Потом в каждом прямоугольнике выбираем «комнату» — прямоугольник такого же размера как исходный или меньшего (но не меньше, чем 3×3 — более детально об этом будет ниже).
Потом комнаты соединяются коридорами. Но не каждая с каждой, а несколько хитро, из-за того они хранятся в «BSP»-подобной структуре (для более подробных деталей смотрите оригинальный алгоритм).
Коридор, соединяющий фиолетовую и белую секции.
В оригинальном алгоритме и комнаты, и коридоры одного цвета (т.е. равнозначны), поэтому там коридоры просто рисуются поверх комнат. В моём случае исходные комнаты должны сохраняться, так что коридоры рисуются как бы «за» комнатами.
Кроме того, если комната (на рисунке — бирюзовая) пересекает коридор, то она должна делить его на две разные секции (поэтому один и тот же коридор может отрисовываться разными цветами):
И вот что получается в итоге:
Дальше начинается фаза пометки мусорных клеток:
Как я уже писал, никакой сектор не может быть меньше, чем 3×3 клетки. Это из-за того, что сектор обязательно должен быть окружен стенами (как минимум по 1 клетке с каждой стороны), и в нём как минимум должна быть одна клетка свободного пространства:
Поэтому, все те клетки, которые не подходят под это правило, помечаются. Но просто взять, и удалить их нельзя — так пропадает много соединений, и уровень получается очень куцым.
Вместо этого, для каждой помеченной клетки ищется тот сектор, к которому она может примкнуть (соблюдая правило 3×3):
Если клетку так и не удаётся отнести к какому-либо сектору, она удалятся (но не в этом случае — тут всё хорошо).
На последнем этапе эта красивая картинка векторизуется, и нарисованные сектора превращаются в полибоксы — такие полигоны, у которых каждое ребро либо строго вертикально, либо строго горизонтально (вероятно, есть более научное название):
Генерация изначальной геометрии: планировка помещений
За основу была взята другая статья. Этот алгоритм несколько сложнее предыдущего, но тоже не rocket science.
Для начала игровое поле заполняется неким стоп-значением, а затем случайным образом на нём очищается прямоугольная область:
Этап очистки случайного прямоугольника проводится ещё некоторое (тоже случайное) количество раз, и в результате получаются внешние контуры уровня:
В свободном пространстве случайно раскидываются точки роста комнат (минимальный размер комнаты — 3×3):
Начинается первый этап роста комнат — для каждой комнаты выбирается наибольшая сторона, которая ещё может расти, и она растёт на 1 клетку (если есть несколько сторон с одинаковой длиной — случайная из них). Комнаты перебираются по очереди, чтоб не было пересечений.
Затем комнаты преобразовываются в полибоксы:
И начинается второй этап роста — в этом этапе сторона может разделяться на несколько частей. В отличие от первого этапа, она растёт не по одной клетке за раз, а сразу до максимального упора — это позволяет избежать «лесенок» на стыках комнат. Если после прохода по всем комнатам всё ещё остались пустые клетки, цикл повторяется.
В результате получается полностью заполненное пространство:
Далее полибоксы отрисовываются в виде растра, и (как и в случае «BSP»-генератора) начинается этап пометки «мусорных» клеток:
И присоединения их к существующим секторам:
Тут не удалось присоединить все клетки — лишние были удалены.
Результат обратно превращается в полибоксы:
Очистка от мусорных секций
Иногда возникают такие секции, внутри которых не соблюдается правило 3×3:
Можно попытаться такие секции «восстановить», но я пошёл по более простому пути, и просто их удаляю:
Построение соединений
Для каждой секции ищутся её соседи, и в местах соприкосновения таких секций создаются соединения. Соединения создаются с обеих сторон — если секция A соприкасается с секцией B, то будет соединение из A в B и из B в A. В результате получается двунаправленный граф.
Очистка от мусорных подграфов
Иногда, в результате очистки от мусорных секций, получается не один граф, а несколько независимых, как в этом примере:
В таком случае в качестве основного выбирается подграф, «площадь» секций которого максимальна, а остальные удаляются («площадь» взята в кавычки, т.к. хоть и есть возможность посчитать реальную площадь полибокса, я упростил задачу, и считаю площадь ограничивающего прямоугольника — это неправильно, но для генератора подходит).
Очистка от излишних соединений
Если из каждого сектора будет проход в каждый, с которым он соединяется, то на уровне будет слишком много дверей, и будет сильнее ощущаться что он сгенерирован. Поэтому, на этом этапе лишние соединения удаляются:
Для большей рандомизации я не генерирую остовное дерево в минимальное количество проходов, а наоборот, удаляю по одному рандомному ребру за раз (выбирая его случайным образом из всех возможных на текущем шаге).
Хотя, когда это пишу, появилась мысль, что будет вполне достаточно случайным образом выбрать начальный сектор, а удалять рёбра уже более эффективным алгоритмом.
Рандомизация соединений
Здесь и далее иллюстрации пойдут из другой генерации, т.к. в предыдущей была ошибка в генераторе, из-за которой дальнейшие картинки были некорректными.
Но уровень, в котором нет ни одного лишнего соединения тоже не выглядит очень человечным, поэтому вносится некий хаос:
Дальше те секции, между которыми образовались проходы, «сливаются» в одну:
Если вам показалось, что на этой иллюстрации вновь появились удалённые на предыдущем шаге соединения — вам показалось :). Когда я вычитывал текст, мне тоже так показалось, но внимательно присмотревшись к предыдущей иллюстрации становится понятно, что всё ок.
Генерация секретных комнат
На графе выбираются такие сектора, у которых есть только одно соединение:
Если таких секторов будет несколько, то они все собираются в массив, и сортируются по «площади». Затем этот массив обрезается случайным образом (но так, чтоб в нём остался хоть один элемент). Эти сектора и станут секретными комнатами:
Генерация «сценария»
Вначале выбираются сектора, с минимальным количеством свободных соединений (т.е. такие, которые ближе к «краю» графа):
На этой иллюстрации выбран один сектор, но, если бы их было больше — всё равно был бы выбран какой-то один (случайным образом).
NB. Во время вычитки статьи, я смог придумать ситуацию, когда сектор с минимальным количеством свободных соединений не только не будет на краю, но и назначение ему сценария приведёт к непроходимому уровню. На самом деле можно выбирать любой сектор, но только такой, после удаления которого граф бы не распался на несколько подграфов.
Далее выбираются сектора, которые соединены с текущим сектором, и у которых осталось только одно свободное соединение. Они, с некоторой вероятностью, будут использованы для продолжения действия сценария. Например, если бы граф был такой, как на иллюстрации ниже, то сектор, обозначенный вопросом, мог бы попасть в список.
Серым обозначена секретная комната, крестиком — те соединения, которые надо было бы удалить в исходном графе, плюсом — исходный сектор.
NB. Во время вычитки статьи, мне показалось, что условие наличия только одного соединения — слишком строгое, достаточно было бы того же, что и на прошлом шаге — чтоб после удаления этого сектора, граф бы не распался.
Далее этому списку секторов назначается номер сценария (просто число, на этом этапе оно ничего конкретного не значит), а соединения на границах этого списка секторов помечаются как закрытые этим сценарием.
На этих иллюстрациях у разных сценариев будет разные цвета заливки сектора. Они не имеют ничего общего с цветом окантовки сектора (в последующих шагах это исправится, но в этом шаге мне удобней так).
Дальше выбирается очередной сектор, составляется список, и этот список помечается новым сценарием:
Обратите внимание на маленькие синенькие точечки внутри красных квадратиков — так отрисовывается scenario opener — т.е. где-то внутри секции с красным сценарием будет находиться ключ или переключатель, который откроет проход к секторам с синим сценарием.
Так продолжается до тех пор, пока не останется свободных секторов:
Самому последнему сектору не присваивается сценарий, а только scenario opener. Этот сектор будет тем сектором, в котором игрок начнёт игру.
Схематически это можно показать так:
«Открывашка» может быть как ключом или переключателем, так и чем-то иным, например, заданием уничтожить всех врагов в каком-либо секторе (но я не планирую, что в ближайшее время генератор или движок станет такое поддерживать).
Оптимизация соединений
На этом шаге для каждого из соединений выбирается какая-либо одна сторона (как вы помните, изначально соединения генерируются в обе стороны). Это нужно, чтоб уровень выглядел более «ручным», и для упрощения последующих шагов (но для ещё более интересного вида уровня, в ближайшем будущем я планирую сделать шаг «деоптимизации» некоторый соединений).
Создание дверей и окон
Для каждого сектора просматриваются все его соединения (которые после предыдущего шага смотрят только в одну сторону), и на каждом просмотренном соединении размещаются двери и окна.
Чтоб уровень выглядел более интересно, на разных шагах разная вероятность размещения двери или окна:
Выбор действия
Хоть это и не имеет отношения к генерации, но на этом шаге меняется визуализация — теперь окантовка сектора красится в цвет сценария:
Стартовый сектор — светло-серый, конечный — синий. Так же заметьте, что вместо двери у секретной комнаты (тёмно-серая слева) нарисована стенка — всё правильно, это секретная стенка.
Далее выбираются те сектора, в которых можно разместить ключи:
Выбираются они достаточно просто:
После этого, случайным образом выбирается количество ключей на уровне (от нуля до трёх), и затем, случайным же образом, из доступного списка секторов выбираются те, в которых будут ключи.
Процедурная генерация, её история, проблемы и невероятные креативные возможности
В 2013 году во время церемонии Spike Video Game Awards показали игру от которой у каждого из миллиона зрителей шоу одновременно перехватило дыхание. Космическое приключение под названием No Man’s Sky от маленькой почти неизвестной студии за пару часов стало сенсацией о которой писали и говорили все, кто хоть как-то связан с интерактивными развлечениями.
No Man’s Sky должна была стать игрой дающей шанс с джойстиком в руках пережить опыт, к которому человечество стремится в своих фантазиях уже не одну тысячу лет. Представьте себе возбуждение от первого шага по новому миру или найденных на песке следов невиданных существ. Взбудораженный этими картинами мозг рождает закономерный вопрос: «как кому-то удалось создать целую виртуальную вселенную немыслимых размеров?». Ответом будет термин «процедурная генерация» за которым скрывается вечный тренд игровой индустрии, её прошлое, настоящее и невероятный креативный инструмент, который должен стать её будущим.
Разработчики начали использовать эту технологию в конце семидесятых годов. Малая мощность компьютеров того времени не позволяла хранить в памяти большие объемы данных, необходимые для воплощения самых смелых фантазий геймдизайнеров. Процедурная генерация позволила обойти эти ограничения, воссоздавая объекты «на ходу». Одной из первых была «Rogue», игра про поиск сокровищ, в которой подземелья создавались по-новой после каждого старта. В дальнейшем она породила популярный жанр «Roguelike RPG», главная особенность которого «случайно» генерируемые уровни.
Rogue
Несмотря на то, что мощность современных компьютеров больше чем у космического корабля, который отправил первого человека на Луну, процедурная генерация контента используется в огромном количестве современных игр. На то есть две важные причины. Во-первых, генерация с помощью алгоритма позволяет сэкономить деньги и человеческие ресурсы, отдав часть работы на откуп программе, что особенно критично для игровых компаний, находящихся в суровой реальности бизнеса и маленьких независимых студий весь штат которых это пара энтузиастов с горящими глазами.
Civilization V
При всех плюсах процедурной генерации у неё есть свои проблемы. Упомянутая во вступлении No Man’s Sky вышла месяц назад и неожиданно для всех вместо сокровенной мечты каждого игрока, она превратилась в Серсею Ланнистер из той сцены «Игры Престолов», где она голая идет по площади, а толпа кричит ей вслед «позор». Страница игры в витрине Steam пестрит красным из-за подавляющего количества негативных отзывов покупателей, большинство из которых ссылаются на то что в No Man’s Sky «нечего делать». Космос оказался пустым и холодным в самом плохом смысле слова. Это отличная иллюстрация для главной проблемы случайной генерации, так называемого «Negative possibility space». Этот термин уходит корнями в особенность психологии, которая заключается в том что человека постоянно нужно стимулировать, иначе деятельность покажется ему бессмысленной и он быстро потеряет к ней интерес.
Diablo II
Несмотря на то, что обычно процедурная генерация используется для создания большого объема контента в короткие сроки, у нее есть множество креативных применений. Космический артхаус RymdResa создает с помощью алгоритма бескрайние космические просторы только для того, чтобы подчеркнуть одиночество главного героя. Пошаговая стратегия Crusader Kings II перед началом каждой партии просчитывает линии родословных и истории столкновения средневековых монархов. Самая «глубокая» игра в мире, Dwarf Fortress, таит в себе бесконечные возможности жонглируя алгоритмами, объединяя их в одну комплексную систему.
Dwarf Fortress
Одна из самых интересных перспектив применения процедурной генерации это её совмещение с нейросетями, для того чтобы создавать «самообучающиеся» игры, которые будут меняться в зависимости от действий игрока. Что-то вроде системы «AI Director» из Left 4 Dead, подкидывающей вам толпы зомби в самые напряженные моменты, только в разы более продвинутой. Игра станет собственным геймдизайнером, подгоняя под каждого игрока условия, создавая новые механики и меняя на ходу собственный сюжет. Это звучит футуристично, но не более странно чем современные игры выглядели бы для кого-то из восьмидесятых.
Представьте себе эльфа в партии вашей RPG, который посреди выполнения квеста сходит с ума насмотревшись на ужасы войны и самостоятельно отправляется на поиски самого могущественного артефакта чтобы уничтожить весь мир, становясь главным злодеем только в вашей уникальной игре и только в этот раз. Или мафиозного босса в очередной GTA, который решает что вокруг слишком много преступников и начинает по ночам бегать в костюме супергероя, восстаналвливая социальную справедливость, что приводит к новой цепочке заданий. Первые предпосылки к этому есть в Толкиеновской ролевой игре Shadow Of Mordor, которая создает орков комбинируя разные черты характера и сталкивает их в постоянных междоусобицах, приводящих к непредсказуемым результатам. Создатель культового Bioshock Кен Левин назвал её «первой игрой с открытым повествованием», отметив что это будущее, к которому рано или поздно должны придти видеоигры.
Shadow of Mordor
Занимаясь творчеством, люди склонны копировать других и даже самих себя. Стоит одной свежей идее «сорвать банк», как все начинают повторять ее в бесконечном количестве вариаций, создавая продолжения и «клоны», пока она окончательно не исчерпает себя и даже после этого. Случайная генерация наоборот, часто дает непредсказуемый результат, ведущий разработчиков к новым открытиям. «Спросите» об этом у искусственного интеллекта ANGELINA, который создает целые игры по нескольким вводным словам. Создатель «Ангелины», Майкл Кук, ежегодного организует форум Procedural Generation Jam, на котором разработчики со всего мира с помощью алгоритмов создают необычные игры вроде генератора историй Infini-Quest или симулятора мага расследующего убийства The Inquisition.
The Inquisition
Процедурная генерация в играх: что это такое и зачем она нужна
Раньше произведения искусства создавались вручную. В XXI веке для этого есть алгоритмы.
Процедурная генерация — незаменимый инструмент в геймдизайне. С её помощью создают огромные виртуальные миры в Minecraft и No Man’s Sky, а также — отдельных персонажей, уровни, сюжеты и даже игровые правила. Иногда кажется, что в будущем алгоритмы будут делать всю работу за геймдизайнеров — но всё не так просто.
Как работает процедурная генерация
Чтобы объяснить принцип её работы, достаточно колоды карт таро. Возьмите в руки карты, перетасуйте их, а затем разложите на столе согласно правилам — вот вы и получили предсказание, сгенерированное процедурно.
Карты в этом случае служат тайлами — фрагментами одинакового размера, из которых складывается общая картина. Правила же гадания выполняют функцию алгоритма, который эту картину собирает.
Тайлы часто используются в стратегиях: например, в играх серии Civilization карты генерируются из шестиугольников, имитирующих разные типы ландшафта. Игроки при этом могут менять параметры создаваемого мира: его размер, рельеф, количество ресурсов и так далее. Иначе говоря, они «настраивают» формулу процедурной генерации.
Но как сделать, чтобы эта формула каждый раз выдавала новый результат? Здесь на помощь приходит зерно — код, созданный генератором случайных чисел. Этот код «скармливают» алгоритму, который затем выдаёт в качестве результата карту, созданную процедурно.
Тайлы не единственный метод процедурной генерации. Авторы Minecraft и Terraria, например, используют шум Перлина — алгоритм градиентного шума. Изначально его придумали для создания достоверных текстур поверхности. Со временем, однако, дизайнеры нашли ему ещё одно применение — в процедурной генерации ландшафта.
Работает это так: светлые участки шума Перлина считываются как возвышенности, а тёмные — как низины. На их основе алгоритм создаёт приблизительный рельеф будущей карты. Процесс повторяется несколько раз, пока не получается достаточно достоверный ландшафт с горами, долинами и ущельями. После этого мир наполняют флорой, фауной, монстрами, деревнями и так далее.
Генерация миров при этом подчиняется множеству заранее прописанных правил, чтобы избежать досадных нестыковок вроде хвойных лесов в пустыне. Поэтому в Minecraft хвойные леса растут в тундре, а в пустыне можно найти лишь сахарный тростник.
Игровой энтузиаст. Любит видеоигры, настолки и рассказывать всем, как они устроены.
Процедурная генерация как игровая философия
Как правило, мы ассоциируем процедурную генерацию с конкретными жанрами. Например, с «рогаликами» (англ. roguelike), где геймплей строится на том, что вы будете пробовать, умирать и начинать заново. Следовательно, уровни всякий раз тоже генерируются заново — чтобы не надоесть игроку и не дать ему пройти игру на мышечной памяти.
Жанр развился из данжен-кроулеров (англ. dungeon crawler) — игр про блуждания в подземельях. У них уже были все приметы roguelike — скажем, пошаговый геймплей (то есть одна команда соответствует одному действию и ходу) и «перманентная смерть». Классические «рогалики» вроде Rogue 1980-го (её именем жанр и назвали) или NetHack 1987-го только добавили к нему процедурную генерацию подземелий, чтобы повысить реиграбельность.
Со временем требования к жанру смягчились и часть некогда важнейших его элементов перестала быть обязательной — но только не случайно созданные уровни.
Или вот «песочницы», где процедурная генерация служит всему подряд, вплоть до нарратива.
Так, Dwarf Fortress перед началом каждой новой игры генерирует не только мир, но и сотни лет его истории. А RimWorld поручает игроку жизни трёх процедурно созданных астронавтов, чей корабль разбился на планете, также появившейся в ходе процедурной генерации.
Вдобавок игра предлагает на выбор трёх «рассказчиков» — это своего рода «генераторы» истории, каждый со своим стилем повествования. Кассандра строит рассказ по канонам приключенческих повестей, Фиби время от времени даёт время на передышку, а Рэнди кидает игрока в пучины хаоса. Всё для того, чтобы превратить каждое прохождение в уникальный опыт.
No Man’s Sky и вовсе использует процедурное звуковое сопровождение. У игры, конечно, есть альбом с саундтреком, записанный группой 65daysofstatic, и треки из него играют в ключевые моменты сюжетной кампании: например, первая стыковка с космической станцией происходит под крещендо песни «Asimov».
Впрочем, большую часть времени игрок слышит не композиции целиком, а лишь их фрагменты, пересобранные звуковым движком No Man’s Sky. Алгоритм берёт звуки из библиотеки сэмплов, созданных на основе треков 65daysofstatic, и комбинирует их так, чтобы они подходили к моменту. Скажем, прогулки по планете сопровождаются мелодичными клавишными, но как только начинается буря, их сменяет резкий электронный шум.
Похожий приём использовала студия id Software при разработке Doom 2016 года. Саундтрек для игры написал австралийский композитор Мик Гордон — официальный OST в этом случае тоже разделён на множество заранее записанных и грамотно сведённых композиций.
В самой Doom, впрочем, различные треки часто комбинируются между собой: если вне боя на фоне звучит ненавязчивый эмбиент, подкреплённый звуками игры, то во время сражений с чертями играет что-нибудь заметно крайне «тяжёлое». А что именно — зависит и от локации, и от демонов на ней.
Процедурная генерация, конечно, подходит не только для «рогаликов» и «песочниц» — она также помогает при работе над играми с более традиционным подходом к геймдизайну.
Процедурные леса и мегаполисы
То, что процедурное создание локаций может помочь в создании игр с открытым миром, доказали ещё авторы The Elder Scrolls II: Daggerfall в 1996 году. Им удалось сделать из заготовленных ассетов карту размером с Великобританию, где поместились 15 тысяч городов, деревень и подземелий.
Да, локации вышли однообразными, но преимущества процедурной генерации были слишком очевидны, чтобы ими не воспользовались другие разработчики. Например, авторы The Witcher 3: Wild Hunt, которым требовалось создать мир, в 35 раз превышающий размерами карту из второй части. Сделать это вручную было почти невозможно, поэтому команда художников под руководством Марчина Голлента применила кисти.
Кисти — это инструменты с наборами ассетов, а в случае третьего «Ведьмака» — с типами растительности. С их помощью разработчики создали все биомы игры — от тайги на севере до лиственных рощ на юге.
Вдобавок они научили алгоритм распознавать особенности ландшафта, чтобы регулировать плотность растительности. Например, в долинах, в которые стекает дождевая вода, генератор выращивал куда более густой лес, чем на каменистых горных склонах.
Кисти не просто сэкономили время и ресурсы CD Projekt Red — они помогли сделать мир «Ведьмака» куда более живым и достоверным.
Процедурная генерация бывает полезна даже в тех случаях, когда карта создаётся по мотивам реального места. В Marvel’s Spider-Man события происходят на виртуальной версии острова Манхэттен, 80% которого создали алгоритмы.
Разработчики нанесли на карту только основные улицы, достопримечательности и места сюжетных миссий, после чего система генерации прочертила дополнительные улицы и переулки, расставила вдоль них здания и декорировала их. Кое-что, конечно, пришлось подправить — например, крыши, где игрок проводит большую часть времени.
Алгоритм действует и в самой игре: он генерирует уличный трафик, пешеходов и случайные события вроде погонь и столкновений с бандитами. Во время драки он следит, чтобы у Человека-Паука всегда были под рукой предметы, которыми герой швыряется в противников: люки, строительные балки и почтовые ящики.
Можно сказать, система генерации в Marvel’s Spider-Man играет в градостроительный симулятор — с той разницей, что её город — это декорация для истории про знаменитого супергероя.
Алгоритмы в играх, которые создаются «вручную», могут пригодиться не только для работы над локациями. Помните опцию «Создать случайного персонажа» почти в любой RPG? За это тоже отвечает алгоритм процедурной генерации.
И это подводит нас к одному из давних споров…
Процедурная генерация — это хорошо или плохо?
Споры о преимуществах и недостатках процедурной генерации продолжаются столько, сколько существует сам инструмент. И у обеих сторон есть веские аргументы.
За: масштаб. Как отметил Яп ван Мёйден, создатель инструментов для левел-дизайнеров Guerrilla Games, огромный открытый мир Horizon: Zero Dawn был бы невозможен без процедурной генерации. Алгоритм позволил художникам студии не только сократить время на проработку карты, но и быстро редактировать вручную созданные локации.
Космические песочницы No Man’s Sky и Elite: Dangerous и вовсе невозможно представить без этого инструмента. В их вселенных требуются сотни миллиардов лет, чтобы облететь каждую планету, — о том, чтобы создавать их вручную, не может быть и речи.
Против: даже лучшие песочницы вроде Minecraft или той же No Man’s Sky страдают от однообразия. Обе игры предлагают впечатляющие вариативностью биомы, но спустя неделю-другую их контент начинает повторяться.
Авторы No Man’s Sky и сами признали эту проблему. Глава студии Hello Games Шон Мюррей рассказывал: «Это и впрямь так работает: игроки встречают одни и те же местности, биомы и планеты». Разработчики попытались решить эту проблему, но отказаться от процедурной генерации всё же не смогли.
Она, к слову, может испортить и более традиционные игры. Bethesda пыталась заполнить мир The Elder Scrolls 5: Skyrim процедурно созданными квестами, чтобы в неё можно было «играть бесконечно». Результат был предсказуемым: система генерации заполнила игру однообразными заданиями по типу «собери пять цветков» и «убей десять бандитов».
За: экономия памяти. Когда локации создаются вручную, каждый объект на них сохраняется отдельно, тогда как, скажем, процедурно сгенерированная растительность хранится в виде отдельной карты. Это позволяет существенно сэкономить место.
Если же алгоритм создаёт целые миры, объём жёсткого диска и вовсе перестаёт быть проблемой — для их загрузки вам нужно только зерно. Именно поэтому No Man’s Sky «весит» чуть больше 10 ГБ: на жёстком диске игра хранит только ассеты, из которых при каждом запуске алгоритм собирает вселенную на 18 квинтиллионов планет.
Против: ошибки генератора. Пример с Watch Dogs: Legion хорошо показывает, что система генерации требует тонкой настройки. К сожалению, предусмотреть все комбинации почти невозможно — значит, всегда есть шанс допустить оплошность, которая сломает баланс или просто выдаст смешную комбинацию.
За: элемент неожиданности. Процедурная генерация — один из главных способов сделать геймплей непредсказуемым. Без неё поклонники Civilization (или Worms) быстро исчерпали бы запас возможных тактик, а фанаты Hades вызубрили бы наизусть каждый уровень игры.
Против: ошибки геймдизайнера. На канале Noclip есть отличное интервью с создателем Dwarf Fortress, где он рассказывает, как открытие баров в игре привело к массовой смерти кошек от алкогольной интоксикации.
Такие дыры в геймплее встречаются и в «обычных» играх, однако процедурная генерация в несколько раз усложняет процесс их отслеживания. Обратная сторона эффекта неожиданности — ни игрок, ни разработчик в точности не знает, чем обернётся следующий патч.
За: возможности для инди-разработчиков. Процедурная генерация — потрясающий инструмент для инди-студий и геймдизайнеров. На момент выхода No Man’s Sky в студии Hello Games работало всего 15 человек. Позже её коллектив вырос до 26 сотрудников.
Minecraft и вовсе создал один геймдизайнер, который после релиза стал знаменитостью, — Маркус «Нотч» Перссон.
Против: меньше рабочих мест для AAA-разработчиков. Экономия ресурсов также значит, что студиям нужно куда меньше сотрудников. Всего три человека в Guerrilla Games нарисовали 500 типов растений для Horizon: Zero Dawn, а их шаблонами занимался один технический художник.
Впрочем, ключевые локации всё равно создаются вручную, да и сам алгоритм кто-то должен программировать. А это значит, что работа для людей всегда найдётся.