Я 2 года писал свою игру на Unreal Engine и он меня ******

Вот уже почти 2 года я наяривал этот треклятый анриал, пытаясь создать оптимизированный открытый мир. И знаете что? Стоковый Unreal Engine вообще не рассчитан на так называемый Open World, который они с таким усердием продвигают последние годы. И сейчас я вам расскажу почему.

Дисклеймер: Я не профессиональный разработчик игр, моя профессия - веб-макака. Однако за эти пару лет я потратил тысячи часов на разработку под UE и чтение форума анриала в попытках отыскать истину, поэтому имею некоторую насмотренность на реальных задачах. Будет круто если в комментах появится пчел, который скажет что я идиот и покажет как сделать правильно чтобы не фризило и не вылетало. Но скорее всего это в очередной раз будет пчел без реального опыта работы с большим проектом.

Багованный HLOD

Для того чтобы создать открытый мир нам необходимо переключить его в специальный “стриминговый” режим, благодаря чему открывается возможность делить огромную карту на регионы. Если мы этого не сделаем, то в конечном итоге для запуска игры потребуется 32гб видеопамяти, 128гб оперативки, рог единорога, шерсть со спины Капитана Джека Воробья… ну вы поняли…

Разметка World Partition по регионам на примере моей игры
Разметка World Partition по регионам на примере моей игры

Разделение на регионы нужно только для удобства работы в редакторе, чтобы легко подгружать/выгружать нужную локацию. Если же мы запустим полноценную игру, карта будет автоматически поделена на ячейки, которые подгружаются на основе близости к камере игрока и вектора его направления.

Скрин с официальных материалов игры
Скрин с официальных материалов игры

Теперь переходим к интересному. Поскольку мы подгружаем только ближайшие ячейки(благо дистанцию и градацию мы можем задать по своему усмотрению), у нас появится необходимость отображать на фоне какую-нибудь гору, холм и прочие крупные объекты. Здесь к нам на помощь приходит HLOD, или как я его называю Багованный Кусок Кала, далее БКК!

Так о чем это я… БКК предназначен для того, чтобы “запечь” ландшафт и прочие объекты в монолитный меш с низким LOD и объединенной текстурой. Как только игрок покидает какую-то область, эта область подменяется на БКК и издалека кажется что ничего и не выгружалось. В теории… На практике как только у вас появится сколько нибудь большая область, БКК в лучшем случае просто кинет фатал на этапе запекания через час, либо, что вообще п*здец, кинет вам фатал после перезагрузки карты. При чем он кинет фатал даже если запекать только ландшафт. Что еще забавнее, это если у вас фатал после перезагрузки карты, то чтобы его поправить придется вслепую искать нужные файлы в папке карты, где находятся тысячи, десятки тысяч файлов с нечитаемыми именами. У вас же есть контроль версий, правда?

В итоге, чтобы оставить на фоне горы, другие острова и т.д. мне пришлось значительно увеличить расстояние для загрузки ландшафта. А я хочу заметить, что ландшафт - очень дорогая штука, и лоды едва ли смогут привести его к тому состоянию, к которому мог бы привести БКК.

Фатальные проблемы с подгрузками

И так, окей, без БКК жить можно, в остальном то все в порядке, верно?

Верно ведь…?
Верно ведь…?

Когда я впервые подключил этот хваленый World Partition, первое что я увидел при попытке посетить/покинуть остров - страшные лаги. Там даже не 6 кадров, там 0.6 кадров. Погрузившись в отладку я обнаружил пару моментов:

Если у вас на карте есть какие-то акторы со сложным Construction Script(например всякие "строители" заборов, книжных полок, дорог и т.д) то у меня для вас плохие новости. Этот скрипт будет исполняться при каждой подгрузке локации. Если вы конечно не придумали как это закешировать(но даже в случае кеширования будут проблемы) или не превратили монолитный меш.

У вас много растительности? Ооо, мой друг! Это ты зря конечно… Я хз как так, но анриал ооочень плохо разбивает растительность на чанки(с новеньким Procedural Content Generation проблема похожая даже с включенным World Partition), и в итоге одномоментно могут загрузиться тысячи мешей если это какие-то джунгли. Вы можете возразить, но ведь это же инстанс статик меши, они почти ничего не стоят(кроме полигонов конечно же)! Но вот тут то и кроется подвох, они ничего не стоят когда они уже размещены на локации. А вот если они попадают в подгрузку, то для каждого меша анриал начинает просчитывать коллизию перед размещением на карте. Вы кстати это можете проверить и другим способом: попробуйте запустить карту с пустым ландшафтом и замерить время её запуска, затем разместите на карте большое кол-во растительности и сравните время запуска еще раз. Скорость запуска будет отличаться в разы, а то и десятки раз(вот кстати пруф пчел с 2020 года ждет, постоянно пост обновляет)

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

В итоге я бомбанул, конвертанул растительность в обычные инстанс статик меши, проставил им дистанцию отрисовки и хоть стало возможно нормально по городу перемещаться. Но фризы все еще сильно били по глазам, а почему? А потому что Occlusion Culling(видит ли игрок какой-то объект или он перекрыт другими объектами и его можно не рендерить) работает как кусок говна! Он конечно уменьшает нагрузку на видеокарту процентов на 10, но ценой этому просадки кадров с 90 до 30 каждые несколько секунд при движении. Пришлось и это вырубить.

В итоге, я снес к херам все удобства работы с растительностью, заборчиками, дорогами, книжными полками и т.д. Только для того, чтобы город работал хоть сколько нибудь стабильно. И знаете что? Эта тварь до сих пор микрофризит при движении и я блять не имею ни малейшего понятия какого хера он там творит за этими BackgroundWorker-ами, потому что треклятый профилировщик просто не дает нормальной информации на некоторые операции.

Загрузка сохранений

И так, в анриале есть система сохранений, пользоваться её не очень удобно, но это решается специальными плагинами. Теперь давайте наложим эту систему на открытый мир и обнаружим один мааааленький такой неприятный момент… Карта ВСЕГДА загружается на первоначальной точке спавна игрока. Т.е. игрок допустим начал игру в центре карты, потом прошел 10км, сохранился, вышел из игры. Потом он снова заходит в игру, загружает карту и анриал загружает центр карты. А дальше разработчику необходимо телепортировать игрока вручную в область его сохранения. А эта область кстати еще и не загружена, т.е. под ним нет коллизии и если его просто отпустить, то и игрок и все ближайшие нпц и физические объекты - упадут под карту. Можно принудительно фризить игру, если игрок на незагруженной локации, но тогда будут фризы если слишком быстро приближаться к острову на корабле.

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

Кстати динамическая подгрузка работает значительно медленнее, чем если бы локация изначально была загружена на нужной точке.

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

Я 2 года писал свою игру на Unreal Engine и он меня ******

Физика

Вы кстати задавались вопросом, почему на анриале не любят особо создавать игры завязанные на физическое взаимодействие? А все очень просто, потому что физика анриала и оптимизация - вещи несовместимые. Во всяком случае начиная с релиза 5.0. Все дело в том, что начиная с этой версии анриал отказался от отраслевого стандарта - физического движка PhysX и перешел на собственную разработку - Chaos. А производительность этого движка может быть до 4-х раз хуже чем PhysX в некоторых кейсах. И одно из оправданий перехода на него - Open World. А стоило ли оно того…

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

Nanite и Lumen

Вот это настоящий прорыв... прорыв канализации. Я проводил множество тестов нанитов этих хваленых, и во всех случаях производительность с обычными лодами была значительно лучше. Но кого заботит производительность? Сейчас на какой последний ассет пак в маркетплейсе эпиков не посмотри, почти все забивают болт на создание нормальных лодов, просто нажимают галочку включить Nanite, а потом в минимальных требованиях для 60 кадров на ультрах - RTX 4080.

Так эпики эти наниты еще и для ландшафтной сетки выпустили недавно. Я подключил её чисто потестировать что как там, увидел дроп в 20% фпс, посмеялся и выключил. Точно небольшое улучшение картинки стоит столько фпс?

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

Если переводить Lumen в хардварный режим, то вся логика построения теней уходит в видеокарту, и в шейдере материалов параметр Distance Fields перестает работать. Есть специальный флаг, который позволит одновременно строить лучи через видюху и генерить DF софтварно. Однако в таком случае нагрузка на видюху будет не сильно отличатся от обычного софтварного люмена + начинают возникать графические артефакты. А для меня DF являются очень важной графической частью, ведь на это завязано скрытие воды на палубе корабля. Вот так и погибают лучи...

Итог

Можно еще много моментов набросить в сторону самого движка. Например что игра в редакторе и игра в готовом билде - могут работать совершенно по разному, из-за чего приходится через задний проход пытаться ловить баги. Или то что у них из патча в патч ломаются одни и те же фичи, которые затем исправляются только спустя несколько месяцев, чтобы в следующем мажорном патче опять их сломать(привет CableComponent). Или что редактор по КД фаталит и ты теряешь любую мотивацию продолжать работу из-за этого. Или...

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

Помню в одном из последних постов разрабы шаталкера сказали что допилили UE, чтобы он не лагал в открытом мире. Но судя по тряске юзеров - получилось не особо. Хочется задать риторический вопрос: проблема точно только в разрабах игры, или быть может инструмент под названием Unreal Engine 5.x вовсе не то, чем пытается казаться? На мой взгляд, на этом движке хорошо делать всякие коридорники разделенные уровнями. Тогда отпадает множество проблем, разве что производительность физики уже не вернуть. Но любая попытка сделать что либо в открытом мире приводит к ощущению что ты ешь кактус. И чем больше проект становится, тем больший кактус приходится есть. Каждый день. Кактус за кактусом…

Будни работы с анриалом
Будни работы с анриалом
Гугл докс шарит!
Гугл докс шарит!

К слову говоря...

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

Скачать можно тут:

6262
55
22
11
11
84 комментария