Сейчас мы будем заниматься шрексом. Знакомство с Godot через разработку раннера для... Яндекс Игр

Прости меня Шрек, ибо я согрешил и сделал про тебя раннер для Яндекс Игр. Делюсь впечатлениями о Godot, рассказываю как я докатился до жизни такой и как подружить Godot c HTML5 и Яндекс SDK.

Для начала - да, я тот самый местный дурочек, который делает ремейк Shrek 2 The Game на Unreal Engine 5.

Почему Godot?

Мне всегда хотелось собрать для себя джентльменский набор инструментов для разработки игр. Unreal Engine прекрасно подходит для карьеры и крутых, красивых и сложных проектов. Но совершенно не подходит для 2D и маленьких проектов для души, которые запустятся на любом ведре.

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

Godot же давно был у меня на примете, и вот я решил сделать на нем проект, который можно будет конвертировать в какой-нибудь профит (лулзы - тоже профит) и заодно привыкнуть к движку.

Яндекс игры? Ходим по дну геймдева.

Сейчас мы будем заниматься шрексом. Знакомство с Godot через разработку раннера для... Яндекс Игр

Я хотел подучить Godot, и для учебы нужен какой-нибудь проект. На dtf в последнее время много статей про Яндекс Игры и я посмотрел, что это такое. Открыл сайт, словил двести баннеров с рекламой (которые смогли обойти ДВА моих adblocker'а), кринжанул, закрыл и забыл.

Но перед этим я приметил, что на сайте видимо модерация пропускает вообще все что угодно и на авторские права всем по боку.

Наверняка это всё игры по лицензии от Dream Works, правда?
Наверняка это всё игры по лицензии от Dream Works, правда?

После этого где-то недельку в моей голове медленно прели следующие мысли:

  • У тебя куча готовых ассетов от Shrek 2 Remake, сделай c ними что-нибудь на Godot
  • Игра может быть и не пройдет модерацию на сайте, но зато получишь опыт работы на Godot
  • А если пройдет, то заработаешь целых 0.69 рублей и репутацию долбаеба

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

У нас есть идея и желание. Но нет знаний о Godot. С чего начать?

Я уже опытный разработчик и мне хватило курса молодого бойца состоящего из двух уроков от Brackeys. Чувак легендарно вернулся после трех летнего перерыва и принес два шикарных видоса про Godot - вот они:

Первое знакомство с Godot
Основы GDScript

Качаем Godot последней версии (это ошибка для Web игры, о чем будет далее), удивляемся что он весит всего лишь около 100 мб (привет Unreal Engine собранный из исходников весом в 200 гб), запускаем и начинаем творить!

Первые шаги

Сначала я поковырял движок, привык к интерфейсу, пощупал GDScript, который оказался Python-like и мне как человеку хорошо знакомым с Python не пришлось привыкать к GDScript.

На контрасте с Unreal Engine - Godot ощущается как молоток с гвоздями - в хорошем смысле.

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

Все что нужно в Unreal Engine для реализации простейшего передвижения персонажа и прыжка.
Все что нужно в Unreal Engine для реализации простейшего передвижения персонажа и прыжка.
Что нужно Godot для перемещения и прыжка
Что нужно Godot для перемещения и прыжка

В принципе, если вы уже знакомы с несколькими движками и с Python, то Godot и GDScript осваивается очень быстро. У него прекрасная документация не брезгующая примерами и подробным описанием функций.

Накидал это на следующий день после знакомства с Godot

Godot и HTML5

Перед тем, как приступать к чему-то серьезному, нужно понять как Godot работает с HTML 5.

Для начала читаем в документации, что Godot версии 4.x плохо подходит для Web игр, а на IOS и Mac так вообще не запускается, поэтому рекомендуется использовать версию 3.x. Я работал на четвертой версии Godot - пришлось качать версию 3.5.3 и работать с ней.

Первая неделя

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

Пример уровня
Пример уровня

С таким подходом имея даже небольшое количество уровней можно добиться неплохой реиграбельности.

Результат первой недели. Можно видеть большое количество растительности, которую выпилил в дальнейшем из-за проблем с производительностью.

Фиксим прыжок

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

Ответ я нашел здесь:

Перевод из абстрактного кода на GDScript:

export var MaxJumpHeight = 2.1 export var JumpDistance = 0.4 var JumpImpulse = 0 var Gravity = 0 func _ready(): JumpImpulse = 4 * MaxJumpHeight / JumpDistance Gravity = 0.5 / MaxJumpHeight func _physics_process(delta): if IsJump: Velocity.y -= pow((JumpImpulse * Global.SpeedAlpha), 2) * Gravity * delta else: Velocity.y = -9.8

Впадаем в депрессию

После экспорта проекта в Web я залил его в черновик на Яндекс Игры и протестировал на 4 мобильных устройствах, на двух из которых были артефакты графики. Выпускать игру, которая в выборке из четырех устройств не работает на двух из них - плохая идея.

Я же вроде не хоррор начинал делать
Я же вроде не хоррор начинал делать

На решение проблемы я убил часов 8 и уже начал сомневаться что решу проблему. В интернете было НОЛЬ информации. Видимо потому, что я один из первых извращенцев делающих на Godot что-то в 3D для Web.

РЕШЕНИЕ ПРОБЛЕМЫ. ЭКСЛЮЗИВНЫЙ КОНТЕНТ ДЛЯ ДАУН ТУ ФАК.

Как это всегда и бывает - дело оказалось в трех галочках.
Заходим в Project Settings\Rendering\Quality и выставляем галочки как на картинке.

Сейчас мы будем заниматься шрексом. Знакомство с Godot через разработку раннера для... Яндекс Игр

После выставления этих галочек артефакты начали появляться и на ПК, то есть я уравнял все устройства - игра перестала работать везде. Осталось сделать наоборот.

Я заметил, что артефакты проявляются только у мешей, которые имеют Skeleton. Обычные Mesh Instance отображаются без проблем. На рандоме я тыкнул в эту галочку и все проблемы решились.

Эту галочку надо снимать для всех мешей у который есть Skeleton, все остальные меши можно не трогать.
Эту галочку надо снимать для всех мешей у который есть Skeleton, все остальные меши можно не трогать.

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

Сейчас мы будем заниматься шрексом. Знакомство с Godot через разработку раннера для... Яндекс Игр

С чувством великой удовлетворенности своим успехом продолжаем работу.

Оптимизируем

С тем уровнем графики на который я замахнулся игра шла на моем трехлетнем китайце за 8 000 в 20 FPS. Больше всего жрет растительность, поэтому от нее пришлось отказаться и оставить только большие и красивые кусты с маленьким количество полигонов.

Ландшафт вручную сделан в Blender из малого количества полигонов. Полигоны которые не видит игрок я тоже на всякий случай выпилил.

Сейчас мы будем заниматься шрексом. Знакомство с Godot через разработку раннера для... Яндекс Игр

Тоже самое касается и всех остальных мешей - полигоны, которые не видит игрок просто вырезаны.

Простите
Простите

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

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

Да и в принципе делать 3D игру на Godot для HTML5 с таргетом на мобильные устройства - плохая идея. Лично я не доволен тому, как игра работает на мобильных устройствах, но поделать с этим ничего не могу. Разве что вырезать все текстуры и вместо моделей использовать абстракции.

Изначально я назвал игру "Бегущий Шрек", но такая игра уже есть на Яндекс играх. Сделана она на Unity.
Изначально я назвал игру "Бегущий Шрек", но такая игра уже есть на Яндекс играх. Сделана она на Unity.

UI

Моих художественных способностей недостаточно, чтобы нарисовать какой либо красивый UI и иконки, поэтому на помощь приходят бесплатные ассеты, которые я взял с itch.io

Чтобы UI нормально растягивался и работал с разными разрешениями экрана нужно проставить следующие параметры в Godot

UI будет растягивать исходя из разрешения выставленного здесь. Если  проставить например 1280 на 720, то на Full HD мониторах все иконки будут зашакалены.
UI будет растягивать исходя из разрешения выставленного здесь. Если  проставить например 1280 на 720, то на Full HD мониторах все иконки будут зашакалены.
В этой же вкладке листаем в самый низ и настраиваем Stretch.
В этой же вкладке листаем в самый низ и настраиваем Stretch.

Выполняем требования Яндекс игр

Выделить стоит следующие требования:

  • Должен быть интегрирован Яндекс SDK.
  • Игра должна быть локализована на выбранные языки.
  • При сворачивании страницы с игрой на десктопных и мобильных устройствах звук прекращает воспроизводиться.

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

Интегрируем Yandex SDK

Вообще для этого уже есть готовые плагины, но это выбор для слабых духом, слабоумные же пишут все сами.

На самом деле все просто, но с нюансами. Godot дает возможность вставить что угодно в HTML Head и вызывать от туда JS код.

JS Код вставляется сюда в настройках экспорта проекта.
JS Код вставляется сюда в настройках экспорта проекта.

Получаем доступ к window, а из него доступ ко всем объявленным в Header переменным и функциям:

var window = JavaScript.get_interface("window") func _ready(): window.initSDK() func ShowAdvBanner(): window.showAdvBanner()

HTML Header при этом должен выглядеть примерно так:

<!-- Yandex Games SDK --> <script src="https://yandex.ru/games/sdk/v2"/> <script> ysdk = null; function initSDK(params) {) YaGames.init(params) .then((_sdk) => { ysdk = _sdk; }) .catch(console.error); } function showAdvBanner(){ ysdk.adv.showFullscreenAdv() } </script>

Чтобы получить Callback из JS функции - создаем его в GDScript:

var OnLoadDataCallback = JavaScript.create_callback(self, "OnLoadData") var window = JavaScript.get_interface("window") func _ready(): window.onLoadDataCallback = OnLoadDataCallback # ВНИМАНИЕ Всегда добавляете аргумент args, даже если не собираетесь передавать никаких аргументов иначе функция не вызовется. Проверенно опытным путем убитых 40 минут в стиле А ПАЧЕМУ НИРАБОТАЕТ func OnLoadData(args): pass

JS:

<script> onLoadDataCallback = null; fuction foo() { // Вызовит функции в Godot onLoadDataCallback() } </script>

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

var array = ["1", "2", "3"] var jsArray = JavaScript.create_object("Array") for item in array: jsArray.push(item) window.foo(jsArray )

Выключаем звук при сворачивании игры и показе рекламы

Для понимания, что игрок свернул или развернул игру я использовал следующий код вставленный в HTML Header :

document.addEventListener("visibilitychange", (event) => { if (document.visibilityState == "visible") { tabActivated(); } else { tabDeactivated(); } });

Внутри игры можно использовать примерно такое:

func TabActivated(args): var MasterIndex = AudioServer.get_bus_index("Master") AudioServer.set_bus_mute(MasterIndex, false) func TabDeactivated(args): var MasterIndex = AudioServer.get_bus_index("Master") AudioServer.set_bus_mute(MasterIndex, true)

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

Локализация

Я просто следовал документации Godot по добавлению локализации в игру. У меня она занимает один *.csv файлик с 11 строками данных.

Чтобы получить текущий язык, нужно использовать переменную из SDK ysdk.environment.i18n.lang

Весь код на стороне игры для локализации примерно такой:

// Для be, kk, uk и uz яндекс рекомендует включать русский язык. var LangReferences = { "be": "ru", "kk": "ru", "uk": "ru", "uz": "ru", "ru": "ru", } func OnSDKInit(args): var locale = LangReferences.get(window.ysdk.environment.i18n.lang, 'en') TranslationServer.set_locale(locale)

Скины?

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

Скин с клоуном можно получить за просмотр рекламы.
Скин с клоуном можно получить за просмотр рекламы.

Вдохновляемся скинами из CS GO и клепаем следующий кринж. Хотели сортир в стиле скина "Азимов"? Я тоже нет, а он теперь есть и обществу придется с этим жить. Несмотря на всю кринжовость и лоск "How Do You Do, Fellow Kids" наклепал 15 скинов и некоторые мне даже нравятся.

Прохождение модерации

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

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

Вместе с "Игра не опубликована" висело предупреждение, что "Монетизация не подключена"
Вместе с "Игра не опубликована" висело предупреждение, что "Монетизация не подключена"

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

Начало клаун фиесты

Отправив игру на модерацию я ждал, что она затянется на 3-5 дней, но уже на следующий день мне пришел отказ в публикации. Модератор нашел несколько проблем:

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

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

Но с другой стороны я до сих пор не понимал как работает модерация. Что если они провели поверхностное исследование и при следующей отправке на модерацию они уже перейдут к следующим этапам и окажется что Godot не годен для Яндекс игр?

Исправив проблемы я отправил игру на повторную модерацию.

Дубль два

Опасения оказались верны, модерация не проверяет всю игру сразу, а видимо находит первые попавшиеся проблемы, отказывает и дальше игру не смотрит. В этот раз проблемы нашли следующие:

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

Почему на первые две проблемы не указали при прошлой проверке - для меня не понятно.

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

Публикация

Не смотря на все, но с третьей попытки игру все таки опубликовали. Если среди комунити DTF есть такие же извращенцы как и я, то смело можете пытаться делать 3D игру на Godot для Яндекс игр.

Я уверен, что будут жалобы на производительность игры (и не только), поэтому я сомневаюсь, что стоит рекомендовать Godot для 3D HTML5 игр, но для 2D это отличный на мой взгляд выбор.

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

Сейчас мы будем заниматься шрексом. Знакомство с Godot через разработку раннера для... Яндекс Игр
3636
19 комментариев

Наконец, кто то что то сделал, а не строит себе наполеоновские амбиции

5

Боже чем я занимаюсь

4

Знал бы ты сколько раз я задавался этим вопрос пока делал это

2

Сделай вместо Шрека Вилсакома, который собирает хомяков.

2

Только на днях думала вернуться из construct в Godot)Спасибо за статью!
* нагло копирует код sdk*

1

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

Чем мне нравится Godot, что очень похож на Python. Не надо ни к чему привыкать. И правильно, что буквально за пару часов знакомства можно сделать свою простенькую игру.

Что мне в нём не нравится: нет интеграции с сервисами, как здесь пример с Яндексом. Если найдешь простое решение для Стима, плиз, черкни мне. Пока это не изучал.