RustyBits | Дневник разработчика
201 subscribers
106 photos
47 videos
7 files
11 links
Дневник разработчика мобильной игры Genesyx
Download Telegram
Прокрастинирую
Я долго думал стоит ли первый бой делать настоящим, т.е. привязанным к серверу и управляемым с него. С одной стороны это хорошо потому, что весь код сразу получится переиспользуемым для других боев, но пришел к выводу, что не стоит, и вот почему.

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

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

В-третьих первый бой - это точка отсечки тех игроков, кому не зайдет жанр. Запускаю рекламу - приходит 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. Если да - насколько они напряжны для вас, как для игрока.
Благодарю всех за комментарии и реакции под ними. Тот факт, что никто не назвал самые проблемные (по моему мнению) места дает некоторую надежду, что дело больше в моем перфекционизме и на них пока можно забить.

Давайте разберем по порядку:

1. Обратите внимание на передвижение бойца в конце видео - поворот влево, перемещение, поворот вправо.
Насколько оно реалистично? На мой взгляд - ни насколько... В реальности человек бы просто передвинулся наискосок. Но... у меня нет такой анимации. И нигде нет, ее можно только сделать под заказ.

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

Кроме locomotion паков на Mixamo есть куча анимаций поворота, но угадайте какая с ними проблема, кроме того, что 95% из них тоже совершаются из состояния покоя? Они сделаны для поворотов на 45-90-180 градусов. На моем гексагональном поле боя повороты нужны на 60-120-180 градусов, т.е. что-то реально готовое я могу взять только для 180, да и то будут вопросы к стойке.

Что я в итоге сделал...
- Взял единственную анимацию поворота влево на 90 градусов, похожую на основную боевую стойку, из Mixamo.
- Сделал ее отраженную версию через функцию мирроринга, чтобы у меня была также анимация поворота вправо (почему-то именно эта анимация поворота на Mixamo только в одном варианте).
- В блюпринте персонажа написал следующую логику: проигрываем анимацию поворота налево на 70%, после этого морфим ее в анимацию передвижения, по окончании анимации передвижения морфим ее в анимацию поворота вправо, которую также проигрываем на 70% и морфим обратно в боевую стойку.
- Еще одна беда в этом подходе в том, что не смотря на то, что и в анимации поворота, и в анимации передвижения, не используется root motion - анимации поворачивают и двигают основную кость (pelvis - эту проблему тоже разбирал ранее), а значит когда персонаж поворачивается - реальный поворот его объекта на сцене не меняется, как и не меняются его координаты при перемещении персонажа анимацией передвижения. Т.е. в моменты переключения анимаций приходится еще вручную менять координаты меша на сцене, не забыв при этом про DelayUntilNextTick между изменением координат и запуском следующей анимации, чтобы логика успела отработать и мы не увидели прыгающего персонажа в одном кадре..

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

Радует и то, что даже это явно получилось существенно лучше того, с чего я начинал здесь.

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

О других проблемах и выводах в следующих постах.
Следующий блок проблем - выстрел Альвареса по Ирвингу:

1. Обратите внимание под каким углом Альварес стоит к Ирвингу при выстреле. Есть у него шансы попасть? Конечно нет жесткого требования всем персонажам стоять именно под углом 60 градусов друг к другу, но если здесь добиваться реализма - придется еще больше нагружать анимации перемещения поворотами, потому что перемещаться-то все равно нужно под углом в 60 градусов.

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

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

4. Нет эффекта попадания в Ирвинга, из-за этого анимацию получения урона можно спутать с уклонением. Но тут снова возникает куча вопросов:
- Добавление эффекта искр сделает еще более очевидной проблему #1
- В каком месте его добавлять? В районе корпуса? А потом я добавлю механику повреждений головы, корпуса, рук, ног и получится визуальное попадание в корпус, но повреждена нога. А если добавлять эффекты на фактических частях тела - выглядеть будет совсем как бред, потому что атакующий стреляет ровно.

Мне кажется пора уже отказаться от идеи реализма и просто найти и принять какой-то приемлемый уровень условностей.
Media is too big
VIEW IN TELEGRAM
Похоже моя борьба с перфекционизмом обречена на поражение.

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

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

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

1. Просадка FPS когда камера меняет крупный план на общий. Назвали дважды.
Честно говоря удивился, что эта анимация воспринимается как падение FPS. Дело в том, что по умолчанию трансформация одного положения камеры в другое производится через линейную интерполяцию координат (функция LERP), за счет этого получается эффект быстрого движения камеры вначале, постоянно замедляющегося к концу. FPS же при этом остается неизменным. Это можно решить через использование другой функции, которая будет трансформировать координаты равномерно, но я не уверен, что это будет смотреться лучше. Пока не буду трогать.

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

3. Вспышка выстрела находится слишком близко к стволу. Подвинул подальше.

4. Походка бойца "в раскорячку" - это артефакт различных скелетов. Как я уже упоминал ранее, анатомия мужчины и женщины довольно существенно различается, т.е. длина различных костей и расстояние между ними разные. Точно также отличаются скелеты моих моделей от стандартных в Unreal Engine и от тех, что генерит Mixamo. Выход здесь один - все анимации делать под заказ, причем мужские и женские отдельно. Может быть когда-то это нужно будет сделать, но точно не до фазы запуска проекта. Пока оставляю это зло как неизбежное.

5. Эффект выстрела похож на выстрел из дробовика, а не автомата. Возможно потому, что анимация отдачи и вспышки эффекта не синхронизированы. Пока оставляю как есть.

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

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

Своего и сторону можно подсветить каким-нить эффектом, низкое здоровье тоже.

Что думаете? Может кто-то видел удачную реализацию в других играх?
Если посмотреть туториалы по UE - складывается впечатление, что на нем делают только шутеры от первого или от третьего лица. Потому многие вещи оттуда в рамках стратегической игры, которая подразумевает другие углы камер, попросту не работают.

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

Начинается все просто - 2д компонент цепляется к 3д модели, но на этом простота и заканчивается. Дальше есть два вида рендеринга - screen и world. Screen подразумевает отображение 2д-информации в экранных координатах, и может показаться, что это то, что нужно... Но нет, привязка координат к 3д модели здесь попросту не работает и почти все туториалы рекомендуют использовать рендеринг 2д через симуляцию 3д-объекта, т.е. World. У них это даже нормально работает. Но не в моем случае...
Не в моем случае потому, что и в шутерах от первого лица, и в шутерах от третьего лица, на примере которых сделаны все туториалы, игрок смотрит на происходящее с той же высоты, на которой находятся противники. И пока третья координата камеры не меняется - все ок. Но в моем случае она приподнята над полем боя, и вот здесь все идет не так и я никак не могу найти правильного решения этой проблемы.

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

Кроме того 3д-объект - есть 3д-объект, по умолчанию он реагирует на освещение, отбрасывает тени и т.п.. Для компенсации всего этого безобразия вам нужно будет сделать кастомный материал, который будет сконфигурен под 2D GUI и будет отключать тени, декали, освещение и прочие фишки из 3д-мира.

Ну и, вишенка на торте - в Unreal Engine очень криво работает наследование на уровне блюпринтов. Вы добавляете 2D-компонент в базовый класс персонажа, ожидаете, что он появится у всех наследников, запускаете игру - и он отображается над тремя из пяти. Идете проверять - компоненты, вроде, есть у всех, но отображаются только у половины. В итоге, как подсказал, ChatGPT, это очень частая "особенность" движка - он может по одному ему известной логике и без явной на то причины оверрайдить настройки компонент в наследниках. В моем случае это и произошло - компонент добавился, но вот его настройки, почему-то прокинулись только в 3 наследника из 5. Таких подстав обычно не ожидаешь и понять что происходит при тоннах галочек и прочих настроек в каждом объекте интерфейса бывает достаточно сложно.
Спустя множество проб и экспериментов, пока остановился на таком варианте. Подытожим:
- Первая строчка - имя персонажа, неотъемлемая часть.
- Ее цвет - оттенки синего (синяя команда), красного (красная команда), зеленого (наш пользователь).
- Под ником чуть мельче отображаем здоровье и энергию в формате текущее/максимальное. Возможно тут, все же, стоит добавить бары, но пока не буду.
- Ключевой момент, который мне подсказал Олег - весь текст имеет черную обводку толщиной в 2 пикселя. Это нужно для того, чтобы текст был хорошо различим как на темном, так и на светлом фоне. Кроме того без этого текст в принципе поверх 3D-картинки читается плохо.

Проблему здесь вижу только одну - не понятно за какую сторону играет наш пользователь. Возможное решение - использовать для идентификации команды отдельный спрайт (кружок, треугольник) разного цвета вместо цвета шрифта. Пока оставлю этот вопрос открытым.
Media is too big
VIEW IN TELEGRAM
Ну... уже, как будто бы, становимся похожими на игру.
This media is not supported in your browser
VIEW IN TELEGRAM
Нашел подходящий пак анимаций для пистолетов. Да, их полно в сторе, но в основном для одного пистолета в руках (что логично). В моем случае нужна поддержка двух и этот набор кажется достаточно простым и достаточным. Анимации не самого высокого качества, конечно, но здесь есть все необходимое (достал/убрал/прицелился/две разных одноручных атаки/одна атака из двух пистолетов/перезарядка). Итого +11 евро к расходам.

На Fab есть и более специализированная подборка из 116 анимаций исключительно для двух пистолетов (https://www.fab.com/listings/32adc703-4c19-4dad-911b-196f76511d77), причем вдвое дешевле, но она мне показалась излишне пафосной и слабо применимой к моему случаю.