RustyBits | Дневник разработчика
208 subscribers
106 photos
47 videos
7 files
11 links
Дневник разработчика мобильной игры Genesyx
Download Telegram
Ребят, если вы присоединились недавно и вам не понятны какие-то технические термины в моих постах - просто читайте блог сначала, там все разобрано и история пока не настолько большая, чтобы сложно было осилить.
Коротко о том, за что я не люблю блюпринты...
Ракурс для боя думаю сделать примерно таким.
Кажется я знаю как игроделы придумывают монстров. Достаточно что-то неправильно сделать со скелетом модели...
This media is not supported in your browser
VIEW IN TELEGRAM
Нет, не получится использовать сделанные под заказ анимации к сожалению, даже не смотря на продвинутый ретаргетинг в Unreal Engine 5. Технически это, конечно, работает, но различия слишком огромны и несовместимы с моими внутренними стандартами качества.

Излишнюю горбатость еще, может быть, можно было бы стерпеть, но плавающие ноги...

Профессиональный аниматор, наверняка, разобрался бы как нужно поправить кастомный скелет и соответствующие анимации для более адекватной конвертации, но в текущей команде (из одного человека :)) такого нет. Придется искать аналоги в Mixamo и сторах.
This media is not supported in your browser
VIEW IN TELEGRAM
Ретаргетинг в Mixamo из стандартного в UE скелета Manny работает лучше. Но есть нюанс...
Наткнулся на первое ограничение блюпринтов по сравнению с кодом - не поддерживаются двумерные массивы.

Мне нужно сгенеренную боевую сетку выставить наружу для того, чтобы дальше на ней позиционировать бойцов в блюпринтах сцен. Самый очевидный метод - создать двумерный массив, чтобы по координатам типа hex[0,2] можно было получить нужную клетку и дальше с ней работать. Но сделать это в блюпринтах оказалось невозможным.

Традиционно ChatGPT об этом не сказал, настойчиво придумывал сказки о том, как это можно нарулить через интерфейс. Причем он постоянно дает инструкции к UE4, в котором интерфейс IDE сильно отличался, и часто проблема решается уточнением типа "а теперь дай инструкцию к UE5". В этот раз такая директива только усугубила ситуацию - "Конечно, ты прав!" сказал ChatGPT и придумал еще какую-то инструкцию, которая тоже крайне далека от реальности, и на проверку которой я снова потратил время.

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

1. Использовать одномерный массив, а индекс вычислять из двух координат. Например X*100+Y. Таким образом всегда получаем уникальное число и его можно использовать как индекс в одномерном массиве. Очевидная проблема такого подхода - фрагментация массива и лишнее отжирание памяти, ведь если для карты 8x4 в двумерном массиве нужно будет создать 32 элемента, то при таком подходе - 8*100+4=804, а заняты будут только 32. Лишний расход памяти.

2. Не использовать массив вообще, вместо этого проименовать добавляемые гексы как 0x0, 0x1,... 7x3, потом искать элементы по имени. Очевидный минус такого подхода - сам поиск. Ведь получение элемента массива - это O(1), а поиск по имени - O(n). Получаем лишнюю нагрузку на CPU.
3. Создать кастомную структуру, единственный элемент которой - одномерный массив, потом создать массив этих кастомных структур и его заполнять. С т.з. производительности это наилучший вариант. С т.з. использования - не очень, потому что если в коде это выглядело бы просто как hexagons[0].arrayItem[2], то в блюпринте получаем целую портянку. Ну да ладно, просто запихну это в отдельный удобный метод.
RustyBits | Дневник разработчика
Наткнулся на первое ограничение блюпринтов по сравнению с кодом - не поддерживаются двумерные массивы. Мне нужно сгенеренную боевую сетку выставить наружу для того, чтобы дальше на ней позиционировать бойцов в блюпринтах сцен. Самый очевидный метод - создать…
В комментариях к посту коллега справедливо заметил, что опция #1 вполне рабочая если для множителя вместо константы (в моем примере 100) использовать максимальную длину массива (в моем случае размер поля по горизонтали). Более того в C двумерные массивы - всего лишь синтаксический сахар, а под капотом лежит одномерный массив, индексы которого так и рассчитываются. Т.е. опция #1 - это фактически и есть реализация двумерного массива в языках, и если об этом подумать - максимально логичная реализация. Век живи - век учись...

И еще один момент по кастомным структурам - это реально структуры, а не классы. Т.е. хранятся в куче и передаются по значению, а не по ссылке. Да, наверное они не просто так называются структурами, но мы уже сталкивались с кейсом Material и Material Instance где терминология не отражает фактического поведения, поэтому этот момент важно уточнить. Причем при использовании кастомных структур возникают странности (от моего незнания движка конечно же) - если создать инстанс структуры, сохранить в переменную, добавить ее (переменную) в массив, а потом что-то изменить в этой переменной - изменение происходит не в том инстансе, который был добавлен в массив, даже не смотря на то, что все манипуляции происходят внутри одного блюпринта. Видимо он где-то под капотом неявно передает переменную как параметр, в результате чего она копируется. Записали, запомнили.
This media is not supported in your browser
VIEW IN TELEGRAM
Убираем трупы с поля боя через динамический material instance, смешивающий основную текстуру персонажа со стандартной текстурой шума и применение маски непрозрачности (opacity mask).
Прокрастинирую
Я долго думал стоит ли первый бой делать настоящим, т.е. привязанным к серверу и управляемым с него. С одной стороны это хорошо потому, что весь код сразу получится переиспользуемым для других боев, но пришел к выводу, что не стоит, и вот почему.

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

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

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

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

Сделал общий блюпринт бойцов, перевел все модели и блюпринт сцены на его использование. Набитые шишки:

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

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

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

4. При удалении объекта со сцены, его чайлды не удаляются и в движке нет для этого стандартного метода. Придется написать свой, благо статические классы и методы в UE есть.

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

6. Иногда просто перезапуск редактора убирает странные артефакты, появившиеся после рефакторинга.
В своем рассказе о декалях я писал, что они работают по принципу прожектора, соответственно если вы добавили трещины на асфальте с помощью декалей, а потом на их место встал боец - трещины будут на нем, а не на асфальте, потому что прожектор - есть прожектор. Чтобы этого избежать нужно отключить рендеринг декалей на бойцах. Делается это одной галочкой, но я тут, как обычно это и бывает, сделал все по классике... Т.е. рассказал и не сделал.
This media is not supported in your browser
VIEW IN TELEGRAM
Наверное набирать команду нужно будет начинать с аниматора, уж слишком много у меня в этой области проблем... Может кто-то уже делал шутеры и знает к какой кости прикреплять винтовку? Сейчас крепится к правой руке и вот что получается. Если прикреплю к левой - винтовка будет держаться за правую руку и выходить из левой...
Занялся эффектами.
Media is too big
VIEW IN TELEGRAM
А вы знали, что эффекты в фильмах тоже делают на Unreal Engine?

Это туториал по созданию эффектов выстрела с летящими пулями и искрами при попадании в цель на примере сцены из Годзиллы. Видео дает не только понимание того, как работает система эффектов на частицах в движках, но и какой картинки можно добиться, когда за дело берется профессионал.
This media is not supported in your browser
VIEW IN TELEGRAM
Ну вроде пазл сошелся, наконец начинаем бой.
This media is not supported in your browser
VIEW IN TELEGRAM
Какой же плохой была идея делать проект без аниматора...

Ребят, тут мне нужна ваша помощь. Посмотрите этот короткий рендер с телефона в нормальном FPS и напишите:
1. Видите ли вы здесь проблемы
2. Если да - насколько они напряжны для вас, как для игрока.