Корсарская химера и чем её готовят. Новое море, оптимизации кораблей и анонс геймплейного ролика

Здравствуйте-здравствуйте, господа! В этот раз я задержался со статьей о разработке. Но сами знаете как это бывает… сперва одно аниме посмотрел, потом второе, потом в игру на сотню+ часов зашел… а еще на работе накидывают неприятных задач, которые нервы треплют. В общем жизнь полная бессмысленных забот. Так к чему это я? Ах да, разработка! В этой статье я расскажу вам о переходе на новое море, полной переработке архитектуры кораблей в угоду производительности, ну и разумеется моего бомбления с ядского анриала.

Новое море

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

  • Из коробки нет возможности настроить следы на воде от корабля(но эту проблему теперь можно решить через интеграцию с FluidNinja).
  • Получение информации о высоте волн осуществляется через довольно дорогую блюпринт функцию, и это очень плохо работает при большом кол-ве кораблей.
  • Поддержка плагина оставляет желать лучшего. 6-ю версию обещают уже черт знает сколько, вроде как этим летом планируют выпустить, НО! Разраба забанили в сторе эпиков за какие-то махинации(уже разбанили, но что-то мне кажется релиз теперь точно затянется).
  • Не самая красивая вода на рынке.

Остается загадкой, откуда такие высокие оценки для этого плагина… Вывод простой - не покупайте плагины до тех пор, пока не будете на 100% уверены, что это то что вам нужно.

К сожалению, есть не так много плагинов для хорошего моря. Я бы даже сказал что их толком и нет. Анализ доступных вариантов я проводил на момент мая, и по сути альтернативой по функционалу на тот момент был только Waterline PRO. Но он тоже не без проблем:

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

Самая красивая вода у FluidFlux, но плагин не подходил для огромного моря… НО! В начале июня разраб выкатил вторую версию плагина, в которой сделал побережье невероятно красивым, с перекатывающимися волнами, и самое главное - бесконечное море! Также, смена высоты волн работает вообще без урона производительности, в отличии от того же Waterline PRO. Так что теперь можно будет правильно сделать штормовую погоду! Однако разумеется без проблем не обошлось:

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

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

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

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

Ах да! У нового моря теперь есть такой параметр как течение, так что в игру добавится новая переменная которую придется учитывать при перемещении. Вероятно оно будет сделано более-менее статично в разных частях архипелага и независимо от направления ветра.

Производительность и корабли

Когда в начале года я был молодым неопытным в геймдеве масленком, я написал статьи о том, какие у меня модульные корабли. Каждая мачта, рея, парус, трос, пушка - это отдельные акторы, с инкапсулированной логикой. Ух ебать какой я ООП архитектор! Так вот, как вы думаете, сколько кораблей с такой архитектурой я мог разместить на карте без того, чтобы мой фпс опустился ниже 30 кадров?

Сколько?
30
17
10
6
3

И правильный ответ: 10! Но это сильно зависело от кораблей. Мановар например сразу сильно просаживал фепесы, я уже даже не помню насколько…

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

Немного посовещавшись с единомышленником, мы пришли к выводу что почти все тросы нужно сделать частью меша мачт. А сами мачты сделать скелетал мешами в которых уже включены паруса, реи и статичные тросы. Динамические же тросы по прежнему спавнить средствами UE. Спустя какое-то время я немного пересмотрел эту идею. И решил разделить корабль на 2 части:

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

Может возникнуть вопрос, зачем пушки в скелетал меш то? Они же статичные! А идея в том, что каждая пушка имеет свою кость, а на кость можно задать коллизию, попадание по которой можно считать как повреждение пушки, что очень удобно! Но и это еще не все, если кости задать нулевой размер, то пушка исчезает с палубы. Таким образом, можно будет реально удалять пушки если они взорвались.

Пример сокрытия пушек
Пример сокрытия пушек

А что же насчет динамических тросов? А ответ как их реализовать всегда был на поверхности. Просто нужно было объединить трос с парусом в единый меш, и применять к нему Shape Keys вместе с этим тросом. Все гениальное - просто! Однако этим тросам нужно задать отдельный материал, чтобы всегда была возможность их скрыть. Зачем? Затем, что при генерации лодов через UE, есть вероятность что тросы превратятся в треугольник, который очень сильно режет глаза.

Анимации в таком кейсе легко поместить в анимационный блюпринт. Я создал несколько анимаций где указал как реи себя ведут при разном направлении ветра и какие паруса поднимаются в каком режиме. Затем просто сблендил это дело в анимблюпринте по параметрам которые приходят из актора корабля и от плагина погоды. Разве что эффект раздувания парусов пришлось уже в тике реализовывать.

Экспериментирую пока что с 3-мя уровнями поднятия парусов
Экспериментирую пока что с 3-мя уровнями поднятия парусов

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

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

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

Теперь можно разместить 50+ кораблей и удерживаться в 45-50 кадрах в редакторе(а если объединить материалы на корпусе корабля, то 50-55, но мне пока что лень), в конечном билде должно быть значительно производительнее. Узким горлышком теперь стали команды на отрисовку материалов с морф таргетами, с ними справиться уже не легко. По идее это можно было бы решить через конвертацию всего корабля в статик меш и прикручивание анимаций через вертексную анимацию, как я сделал с персонажами. Однако корабль это очень комплексная система, и для него потребуется смешивать разные анимации, чего VAT плагин пока что не может. Я хотел сам пошаманить в этом деле, но у меня в принципе анимации не записываются под эти корабли, хз почему. Т.к. мне хватает текущей производительности, я забил на это болт. Однако тут еще похоже что не работает отключение рендеринга когда камера не смотрит в сторону корабля, надо будет еще покопать это дело.

Новый источник кораблей

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

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

А, ну и да, я наконец-то распилил класс корабля на целую кучу отдельных компонентов, чтобы было проще вести разработку. Каждый компонент теперь имеет C++ родителя, чтобы в будущем в нем реализовывать какую-то требовательную логику. Но и тут не без приколов… гребаный UE теперь иногда может намертво зависнуть если я попробую удалить более ненужное поле в блюпринте.

Корсарская химера и чем её готовят. Новое море, оптимизации кораблей и анонс геймплейного ролика

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

Если в целом говорить о выводах по кораблям, то идея создавать игру на новом движке, придерживаясь правил старого движка - говно. Я потратил кучу времени чтобы придумать как сделать то, что по большей части незначительно. Да, я стал лучше понимать что в движке легко сделать, а что лучше даже не пытаться. Но стоило ли оно того, коль я не собираюсь в профессиональный геймдев? Например те же паруса, люди давали светлую мысль просто сделать шаблоны парусов, а потом их переиспользовать на всех кораблях. Но я же упрямо следовал догме, что все должно быть максимально близко к оригиналу или его превосходить. А еще пробовал автоматизировать там, где проще было бы уже руками сделать. Дебил? Дебил.

Конец моему ремейку корсаров

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

  • Медленный ход корабля обязывает меня, как разработчика, добавлять ускорение времени. Добавляет ли это иммерсивности? Сомневаюсь. Так это еще и добавляет проблем с реализацией, ведь UE не ускоряет физику больше чем x2. Из-за чего мне пришлось отказаться от физики самого UE, и реализовывать свою говно-логику перемещения.
  • Неспособность идти против ветра тоже относится к первому пункту, из-за крайней медлительности происходящего. Я не говорю что в игре не должно быть ветра, я говорю что ветер должен быть весомым бонусом, а не жизненной необходимостью.
  • Стрельба - отдельный мазохизм. Допустим ты сталкиваешься в море с противником и он начинает тебя обстреливать ядрами чуть ли не за километр(в ендгейме, ибо только тогда есть соответствующие пушки). У тебя 2 варианта. Либо ты тоже начинаешь как дибил тратить ядра обстреливая его, и может, минут через 5 с диким ускорением, ты его все таки потопишь. Либо ты поднимаешь паруса, и плывешь навстречу к нему, что в конечном итоге приводит к тому, что у тебя убиты паруса, и ты теперь черепаха без ног. Конечно можно изворачиваться своевременным спуском парусов, но если противник не один - удачи. Мне собственно поэтому нравится морская боевка начальных и средних уровней, потому что там ты сражаешься на средне-близких дистанциях.

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

А кто этим недоволен - может пройти н… на обучающие сайты по игровым движкам, и сделать свой ремейк мечты.—

Послесловие

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

  • прогулка по населенному городу
  • общение с NPC
  • получение квеста
  • выход в море
  • морская битва и затем сдача квеста в городе

Хотелось бы еще показать работоспособность статов и перков, но я под это еще не создал интерфейс…

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

3434
11 комментариев

Самая красивая вода у FluidFluxа разраб смотрю тот еще юморист

2

Ждём ролик, успехов!

2

Парусники = секс
Удачи тебе бро!

1

Я понимаю, что много зависит от настроек, но всё же если сравнить воду по производительности FluidFlux, Oceanology и стандартную воду UE, даже не сравнение, а скорее субъективное мнение, что лучше? Вообще, если ты столько времени уделил воде, хотелось бы услышать на эту тему более развёрнутое мнение, в первых постах почти все шаги были расписаны, не по воде, а вообще, понимаю, что возможно нет времени всё подробно писать, но очень бы не хотелось, что бы статьи превратились в дальнейшем в "Переделал город - стало лучше".

Если говорить о дефолтных настройках, то производительность следующая:
UE вода > Океанология > FluidFlux. Но с учетом того, что у океанологии беда с методом получения высоты волн, что для меня критично, то у меня в реальной игре получается что FluidFlux более производителен. В общем все от сферы использования зависит...

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

1

Мне интересно как ты планируешь соединять передвижение по глобалке? Это будет как в оригинале с мини картой,или большой бесшовный мир?Если второе,то очень интересно как это будет выглядеть,потому что я даже представить себе это не могу,как будут встречаться корабли,с учетом того что они все разные:есть торговцы,пираты,военные конвои и тд.Со всеми разное взаимодействие,это ж пиздец

Бесшовный мир по большей части.
Ну, следует понимать что логика старых корсаров уже не налезает на большой мир. Я пока что имею у себя в голове только верхнеуровневое представление поведения кораблей в мире.
Капитаны не будут в 100% случаев нападать на торговцев и каперов других стран. Если в радиусе огневого поражения будет возникать неагрессивный вражеский корабль, то будут производится только предупредительные выстрелы и попытка выйти из радиуса соприкосновения. Если корабли идут на сближение - начинается полноценный бой.
В свою очередь, корабль противника будет вести себя точно так же, если только он не пират или капер с пустым трюмом.
В теории так корабли могут вообще сбиться с маршрута сильно, но с точки зрения игрока, это почти не имеет значения.

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