Как я планету в Unity генерировал

Это вторая часть истории о том, как разрабатывалась игра «How do you like it, Elon Musk?», в которой я оставлю счастливые озарения позади и поговорю о страданиях с Unity, которые незамедлительно появляются, когда ты хочешь создать на движке чуть больше, чем просто 2D платформер.

В одном шаге от No Man's Sky каким он был на релизе
В одном шаге от No Man's Sky каким он был на релизе

Прошла неделя. У меня на руках была работающая атмосфера Земли, упрощенная симуляция полета, три модельки ракеты и одна система частиц для двигателя, а еще десятки обычных и процедурных текстур ландшафта, металла и деревьев. Не то чтобы всего этого хватало для реализации полноценной игры по моим новым идеям, но это было началом. Однако я всё никак не приближался к разработке строительства и развития космодрома — в голове еще не сформировалась окончательная картина того, чего я хочу, задача казалась слишком большой и было непонятно, с какой стороны к ней подступиться. Поэтому я решил пока заняться следующей итерацией прототипа — генерацией поверхности планеты.

Как всегда, в Unity не было встроенных инструментов для решения этой задачи. Terrain — единственный инструмент, который похож на то, что мне нужно, но он способен генерировать только плоские поверхности без возможности поворота, безнадежно устарел (даже с учетом последних обновлений в версии 2018.3), никак не расширялся, и к его исходникам невозможно было бесплатно получить доступ. Поэтому нужно было срочно задействовать свои навыки, корнями уходящие в университетские годы.

Поиск решений

Одна из немногих вещей, которой учит тебя университет — это максимальное уменьшение объема затраченных усилий на единицу задания, путем основания своей работы на базе того, что было сделано до тебя. Иными словами, зачем писать записку к курсовой с нуля, если можно найти готовую у ребят старше курсом и переделать лишь отличающиеся части? Этот принцип в менее искаженном виде отлично работает для программирования. Для любой поставленной задачи есть 99%-я вероятность, что ее решили до тебя и более умные чем ты люди и 33%-я вероятность, что они рассказали об этом в блоге, на GDC или даже выложили исходники. С учетом количества подводных камней, которые каждая задача в себе таит, любой поиск информации о ней будет себя окупать.

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

Первым стоит выделить Proland и его порт на Unity. Красиво, масштабно, с использованием физически корректных данных. Это казалось именно тем, что нужно, однако я наткнулся на две серьезные проблемы. Во-первых, лицензия (на момент моих поисков) не позволяла использовать Proland и все его производные в коммерческих продуктах без дополнительных согласований. Конечно, можно было пообщаться с французскими коллегами, продать свой холодильник и диван и оплатить стоимость неисключительной лицензии, если бы не вторая загвоздка. Она заключалась в том, что портирование исходников с C++, который я знал на уровне университетских лабораторных работ, заняло бы у меня больше времени, чем написание аналогичного проекта с нуля на C #.

Работы над библиотекой закончились в 2013 году, но ее картинка впечатляет до сих пор
Работы над библиотекой закончились в 2013 году, но ее картинка впечатляет до сих пор

А готовый порт, к сожалению, базировался на одном огромном костыле. Проблема заключалась в том, что Proland основан на системе координат, в которой ось Z направлена вверх, а в Unity вверх направлена ось Y. И автор порта разумно упростил себе жизнь, сохранив оригинальное направление осей и просто заменив MVP матрицу у камеры. В последней версии Unity это ломалось и изображение рендерилось зеркально-перевернутым. Даже если на это закрыть глаза, такой костыль все равно неприемлем: работать, когда у тебя половина проекта основана на другой системе координат будет невозможно.

Просто возьми, поменяй оси и пересчитай все матрицы, делов-то.

читатель с научной степенью в линейной алгебре

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

Следующим я нашел SpaceW. Все еще красиво, с намеком на расширяемость в полноценную солнечную систему. Этот проект запустился и даже работал на последней версии Unity без нареканий, но автор признался, что некоторые компоненты все также используют инвертированные оси и куски Proland, другие взяты из Space Engine, в коде много черной магии, экспериментальных фич, и вообще всё это не готово для использования в играх. По моим ощущениям кода и функционала там было еще больше, чем в Proland. Жаль, что автор прекратил активную разработку в 2017 году.

В проекте даже работали солнечные затмения
В проекте даже работали солнечные затмения

UnityProceduralPlanets был практически полной противоположностью первым двум проектам, реализовывал самый базовый функционал генерации и мог бы послужить неплохой отправной точкой к пониманию проблемы. Но проект не запустился, оказался в принципе заброшен автором, правильно строил планеты только радиусом меньше десяти километров (радиус Земли, для сравнения, 6371 км) и не был готов для использования в играх.

Выглядит в лучших традициях Unity, но главное ведь то, что внутри
Выглядит в лучших традициях Unity, но главное ведь то, что внутри

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

В магазине ассетов Unity дела обстояли еще хуже, да и качество продуктов в нем по медиане еще ниже, чем качество самых дешевых инди-игр в Стиме, поэтому я смирился, что готовых «в один клик» решений мне не найти и перешел к поискам теоретического материала.

Исследование предметной области

Информации о том, как генерировать планеты в интернете попадалось много, однако она была размазана тонким слоем между форумами-мамонтами вроде gamedev.ru, туториалами на Ютубе, статьями в личных блогах и неполными ответами на Stackoverflow. Всю информацию я фильтровал через свой набор требований, выжимал из нее воду и шутки авторов, а сухой остаток складывал в общую копилку до тех пор, пока масса знаний не достигла критической и позволила мне приступить к работе.

Весь «список литературы» приводить здесь нет смысла, но я остановлюсь на трех ссылках. Для начинающих свой путь по чудесной преисподней Unity советую серию видео туториалов Себастьяна Лига, одного из ведущих графических разработчиков движка. Он опустил некоторые сложные детали, вроде динамического LOD, однако базовое представление о процедурной генерации получите.

Любителям хардкора и тем, кто не воспринимает информацию в разжёванном виде, можно обратить внимание на «старую», но от этого не менее ценную статью «Планетарный ландшафт». Статья подкреплена формулами, примерами кода на C++ и шейдерами на HLSL (или GLSL? они все на одно лицо) и является наиболее полным руководством к действию из тех, что я видел. Однако здесь нужно включать голову и понимать, как подходить к материалу через призму имеющихся инструментов Unity. Если, к примеру, кинуться реализовывать отсечение по пирамиде видимости из статьи, то можно потратить большое количество времени впустую.

И, напоследок, классика жизни, хрестоматия космических полетов и Святой Грааль безупречной физической симуляции — выступление на GDC разработчиков Kerbal Space Program. Генерации планет там посвящена всего четверть видео, да и в целом описаны общие концепции без конкретики, но слушать интересно и можно избежать пары грабель. Рекомендую.

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

  • Планеты должны быть большими, в идеале соответствовать размерам небесных тел нашей Солнечной системы.
  • Нужно по-максимуму использовать возможности движка и избегать костылей, пока это возможно.
  • В крупном масштабе должна использоваться заданная карта высот (чтобы можно было использовать ландшафт реально существующих планет), а детали при приближении должны генерироваться процедурно.
  • Текстуры должны подбираться системой из заданного набора в зависимости от климата в текущей области.
  • Должна быть предусмотрена возможность добавить флору, реки и объекты искусственного происхождения в будущем.
  • Система должна быть совместима с разработанной ранее атмосферой, работать быстро и выглядеть красиво.

Перечитав список требований, я на секунду задумался, а не вернуться ли к разработке убийцы Масс Эффекта, но пути назад уже не было. Скрипя зубами, я выписал список задач, с которыми мне предстояло столкнуться, и он удивительным образом оказался не таким устрашающим. И мы пройдемся по каждой задаче и моим вариантом ее решения в следующей статье на DTF.

Напоследок еще раз оставлю вам страницу игры в Стиме и ссылки на каналы в Телеграме и Дискорде. До скорой встречи.

148148
100 комментариев

Дневник обрывается, почти что дойдя до кульминации)
Странно, что с таким серьезным подходом к разработке, название довольно несерьезное выбрано.

20
Ответить

Комментарий недоступен

26
Ответить

На самом деле я готов уже было пуститься во все тяжкие и начать вбрасывать куски кода, но мне было не понятно, приветствуется ли подобный формат и интересна ли тема аудитории. + Статья уже стала приближаться к критическому объему, после которого ее никто не читает.

6
Ответить

Да. Надо бы всё-таки "What about this, Elon Musk?"

2
Ответить

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

7
Ответить

Иccледование предметной области, мля XD ты диплом сел писать, или статью на dtf? Тут метро в eps выпускают, и mudfish обасрались XDD

3
Ответить

Комментарий недоступен

4
Ответить