GameDevLogs
187 subscribers
7 photos
7 links
Заметки разработчика игр. Тут поднимаются как технические темы, так и общие темы связанные с разработкой игр. https://agulev.com
Download Telegram
Channel created
Провел небольшой эксперимент с html5 играми.
Обновил 2 игры из 4. Обновления включают:

- добавление процента загрузки на лоадер скрине;
- исправление бага в Chrome, когда игра загружается в отдельной фоновой закладке, иногда iframe может иметь размеры 0х0.

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

В общем вывод такой:
- делайте явным процесс загрузки. показывайте проценты на экране. Желательно еще и с анимацией, чтобы пользователь точно видел прогресс;
- убедитесь, что игра открывается и загружается в фоновой вкладке без проблем. В Defold это исправлено в 1.2.181, но если используете более раннюю версию, то обязательно посмотрите этот PR и примените эти изменения в ваш шаблон: https://github.com/defold/defold/pull/5641/files

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

TLDR:
Если в приоритете оперативная память, то лучше использовать
ASTC 6x6 или 4x4 если качество нужно очень высокое (6х6 выглядит довольно хорошо, для большинства текстур)
——если не поддерживается——>
PVRTC 4bbp для iOS или ETC2 для андроид
——если не поддерживается——>
RGBA, а что поделать

Если в приоритете размер на диске или скорость скачки, а оперативная память уже не так важна (например для HTML5), то лучше использовать WebP lossy, подобрав допустимое качество (Но это компрессия, текстура в памяти будет стандартная RGBA)

——
Самым лучшим вариантом является ASTC - это просто боженька компрессий. Мэтры которые даже снят компрессию пророчат ему то, что он станет убийцей всех форматов если придет на PC (с Apple M1 это уже становится реальным и надеюсь остальные подхватят, но посмотрим).

У него соотношение качество/размер очень классное + есть возможность играться с качеством меняя размер блока. https://android-developers.googleblog.com/2015/01/efficient-game-textures-with-hardware.html

6x6 подойдет почти всем при этом в памяти занимает меньше даже чем PVRTC 4bbp.

Для RGBA текстуры размером 2048х2048 занимаемая память будет такой:

ASTC 6x6 - 1.8Mb
ASTC 4x4 - 2.4Mb
PVRTC 4bbp - 2Mb
ETC2 - 4Mb

Если качество нужно повыше, то есть ASTC 4x4 - там к качеству сложно придраться.

Но из-за того, что покрытие не 100% приходится рассматривать другие форматы. PVRTC 4bbp и ETC2.

Аппаратная поддержка ASTC появилась только с A7 (iPhone6) а iPhone5s хоть уже и на Metal, но все щее не поддерживает ASTC. Поэтому если вам нужна поддержка iPhone5 и его ровесников (iPad Air, iPad mini 2/3), то вам нужен PVRTC.

ETC2 для андроидов, что не поддерживают ASTC. Cтатистика тут https://developer.android.com/guide/app-bundle/asset-delivery/texture-compression
ETC2 поддерживается всеми устройствами с OpenGL ES 3, поэтому если у вас есть такое минимальное требование на проекте, то поздравляю, ETC2 ваш вариант. А вот если вы поддерживаете OpenGL ES 2 придется подумать и про другие варианты и ухищрения.
В Defold используется Basis Universal UASTC, чтобы решить вопрос компрессии как с точки зрения энкодера (кроссплатформенный PVRTC энкодер, это та еще головная боль) так и с вопросом транксодинга в рантайме.
Сейчас в Defold вот такие водопады для текстур.
Правки еще вносятся и форматы уточняются т.к. тема обширная. Но сам подход гарантирует, что будет использоваться оптимальный формат текстуры, поддерживаемый железом на каждом конкретном устройстве. Размер basis контейнера на диске тоже меньше за счет оптимизации для LZ компрессии.

Но на многих WEB проектах приоритеты могут отличаться и самым важным является размер ресурсов на диске(сколько качать пользователю). И, как оказалось, наилучший вариант по размеру/качеству выдает WEBP lossy.

Небольшое сравнение Basis и WebP с точки зрения размера файлов (оно не учитывает остальные характеристики).
Помимо WebP и UASTC в сравнение включен ETC1s (BasisU), который, как мне кажется, даже при максимальных настройках качества, не пригоден для игр.
У меня появилась возможность проверить насколько механизм докачки файлов при плохом соединениее влияет на метрики HTML5 игры.

Ситуация такая.

Defold в своем шаблоне HTML5 учитывает очень многие аспекты работы с вэб играми. Одним из таких аспектов является и повторная попытка докачать файлы в случает проблем соединения.

Но совсем недавно @aglitchman обнаружил, что в Defold версии 1.2.175 механизм, что делает попытку повторно загрузить файл в случае ошибки xhr, сломан. Это не самый очевидный механизм, поэтому такое случается, когда переписываются большие куски кода. Артем исправил это в версии 1.2.182.

Но вернемся к играм.

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

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

Таким образом у меня получается очень чистый эксперемент, где я не пересобирая игры (а значит ничего не меняя) проверяю только одну конкретную фичу и ее влияние.

О результатах эксперемента расскажу через несколько дней, когда будут данные.

Подписывайтесь, чтобы не пропустить.
GameDevLogs
У меня появилась возможность проверить насколько механизм докачки файлов при плохом соединениее влияет на метрики HTML5 игры. Ситуация такая. Defold в своем шаблоне HTML5 учитывает очень многие аспекты работы с вэб играми. Одним из таких аспектов является…
Эксперемент казался идеальным, но время было подобрано плохо.
В первых числах июля, сразу после обновления игр, просели все показатели.
Такая классическая летняя спячка с сокращением рекламых бюджетов. Поэтому вразумительных выводов сделать не удалось.

----

Но зато мы заметили, что у одной из наших игр стоит неудачная иконка. Скорее всего менеджеры портала установили ее на свой вкус, а мы не заметили. Мы заменили иконку на доказавшую свою эффективность в результате A/B тестов на GooglePlay и количество игроков в игре значительно увеличилось, подтянув за собой и доходы. Это, конечно, порадовало в этот летний сезон просадок по всем показателям.

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

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

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

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

Но тут приходишь ты, воодушевленный инди разработчик и приносишь крутую DnD.

И хороший издатель, обычно, говорит: "Знаешь, мы не очень в DnD, иди к кому-то еще".

Честный издатель, которому игра твоя нравится и это интересно, говорит: "Мы ничего не понимаем в DnD, если ты готов с нами рискнуть и мы поучимся за счет твоей игры вместе, то погнали!"

А плохой просто говорит: "Да, не вопрос, погнали!"

И начинает прекрасный DnD начинают продавать как салочки. Делать ему арт как в салочках, примерять на него метрики салочек и делать все то, что они умеют т.е. продавать салочки.

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

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

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

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

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

Вывода не будет. Пусть это будет просто материал для подумать и чтобы ссылаться, когда надумаю рассказать как работаем мы и почему (пока) без издателей.
Я уже упоминал про важность A/B тестов, но давайте разберем подробнее.
А начнем с голосования и постараемся угадать, какая из иконок победила в A/B тесте с отрывом в почти два раза. А через несколько дней я расскажу всю историю подробнее.
Какая из иконок победила в A/B тесте с x2 отрывом?
Final Results
66%
1
13%
2
21%
3
Само голосование является отличной иллюстрацией того, почему A/B-тесты так важны.
Показывая иконку друзьям, обсуждая с дизайнерами и делая опросы, мы находим самую красивую иконку, ту, что эстетически нравится больше.
В таких обсуждениях можно услышать много доводов о том, что эта иконка лучше отражает суть игры или является более чистой и понятной. Все они, чаще всего, верны.
Но задача иконки привлечь пользователя в игру. И не просто абстрактного пользователя, а того, кому игра действительно понравится и он будет играть в нее дальше.

По итогу, перед нами стоит задача не эстетического плана, что является первой, рефлекторной оценкой любого графического изображения, что попадается нам на глаза.
Это задача, скорее, ближе к поведенческой психологии с очень хорошим знанием своей целевой аудитории. Специалистом в этой области я точно не являюсь и, честно говоря, я не знаю людей способных предугадать 3 из 3 результатов A/B тестов. Но это и не нужно именно благодаря тому, что этот инструмент у нас есть, нужно просто не забывать им пользоваться.
Иконка №3 - это первая версия иконки. Она, конечно, не идеальна, но отражала суть игры, на момент ее выхода.
Иконка №1 - это результат большого количества итераций и обсуждений. Все четко и выверено. У нас было много доводов, почему она намного лучше, чем текущая.
Иконку №2 мы решили добавить в последний момент, т.к. мы заметили, что в Google Play можно задать больше двух иконок для A/B теста - почему бы не проверить, как это работает. Сделана она за 5 минут без каких-либо заморочек и обсуждений. Просто филлер.

Как можно догадаться из моего описания выше, именно иконка №2 победила с большим отрывом. Причем отрыв был более чем в 2 раза как для First-time installers, так и по Retained installers 1st day.

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

Сегодня получил письмо от Google Play, суть которого:
...
Your app contains content that doesn't comply with the User Ratings, Reviews, and Installs policy.
...
App status: Removed
...

Что же такого страшного мы натворили?
Прежде чем раскрыть причину, давайте в паре слов расскажу про само приложение.

Итак, у нас полностью бесплатная игра по классической механике.
Полностью бесплатная - знаичт ПОЛНОСТЬЮ бесплатная =) т.е. никаких платежей и никакой рекламы.
- 2.2M+ установок.
- 300k+ активных установок
- рейтинг 4.5+
- Очень маленький билд: 1.6 Mb
- Игра даже не запрашивает permission на доступ в интернет, а значит не собирает никаких данных совсем.

Еще важно упомянуть, что мы обновляем эту игру очень редко. Последнее обновление было Jul 30, 2020.
Но люди любят нашу версию т.к. она очень маленькая, действительно бесплатная и не высасывает батарею как большинство игр.

Итак, что же случилось.
А случилось “злостное” нарушение правил: слово "free" в названии приложения.
За то время, что мы не обновляли приложение, правила изменились и теперь это нарушение правил.

И казалось бы, ну дайте предупреждение с дедлайном на исправление? Нет! Лови удаление до исправления.
Причем исправление - это дело трех минут, а пройти модерацию дней 7.

Если у вас есть игра на Google Play, то обязательно прочитайте эту страницу очень внимательно.

А еще можно подержать меня в twi лайком и/или ретвитом, вдруг это кому-то поможет избежать проблем:
https://twitter.com/AGulev/status/1488595290395451393

UPD: happy(?)end этой истории в комментариях к записи.
Игра бесплатная, но вот такие отзывы бесценны.
Опытным разработчикам пояснять не нужно, что нет смысла смотреть eCPM когда у тебя довольно маленькое количество показов.
Но вот среди начинающих, я часто вижу попытки сравнивать или пытаться рассчитывать потенциальный доход, исходя из eCPM на 500-1000 показов в сутки.

Вот 2 показательных графика.

На первом графике eCPM на платформе Яндекс, где игра перенесена на другой аккаунт и очень наглядно видно, как количество показов падает (зеленый), а eCPM стремится ввысь(желтый).

На втором скриншот из AdMob. Игра тоже переехала на другой аккаунт и некоторая часть игроков все еще обновляется. Видно как просмотры падают. При этом могут случаться вот такие аномалии, из которых никакие выводы делать точно не стоит.
В чате возник вопрос: "А как понять тяжелый шейдер или нет?".

Давайте попробуем разобраться.
Для начала нужно понять, сколько примерно циклов займет исполнение шейдера.
Для этого берем оффлайн компилятор шейдеров (чаще всего это Mali offline compiler) и “скармливаем” ему наш шейдер. Обычно, у движков есть модуль или ассет, который упрощает этот процесс. Как например у Defold это вот такой скрипт для редактора.

Увидели чиселки из которых ничего не ясно? Это нормально, так и должно быть. Желательно пойти в этот раздел документации и внимательно прочитать, что это за чиселки.

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

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

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

Ну вот мы знаем некое условное количество циклов, которое нужно для исполнения нашего фрагментного (пиксельного) шейдера. А дальше то что? Как понять много это или мало?

Давайте посчитаем условный максимум который можно выжать с вашего мобильного GPU.
Допустим, что ваше минимальное целевое устройство это телефон с Adreno 330 на борту и экраном 1920 на 1080 точек.
Пусть это будет хороший Adreno 330 на хорошем чипсете у которого частота 578 Mhz (а не его хилый родственник с 450 MHz).
Мы помним, что MHz - это частота в секунду, поэтому на кадр у нас 578/60 ~ 9,33 Mhz, что примерно 9,33 * 1 000 000 = 9 330 000 Hz (циклов) на кадр.

Это много? Как бы не так.
Размер экране 1920 * 1080 = 2 073 600 пикселей.

т.е. если картинку размером с экран прогонять через наш фрагментный шейдер исполнение которого требует 1 цикл, то сделать мы это сможем 9 330 000 / 2 073 600 ~ 4.5 раза.

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

А теперь смотрим на то, что нам выдал оффлайн компилятор и сравниваем с расчетами. Например мы видим там 4, а мы насчитали 4.5, так что будет 60 FPS и все отлично? Конечно нет, я же говорил, что это прикидка.
Есть много нюансов, к примеру:
- выводиться на экран может значительно больше пикселей, т.к. что-то может выходить за пределы камеры и все равно рендериться;
- где-то могут быть перекрытия и в один и тот же пиксель на экране отрендериться несколько пикселей перекрывая друг-друга;
- а еще мобильный GPU не может работать на пиковой мощности долго и начнет снижать напряжение чтобы остыть, если его сильно нагружать. Поэтому всегда должен быть задел на бездействие GPU, чтобы было время “перекурить” между кадрами;
- а есть же еще вертексный шейдер…
и еще огромное количество нюансов.

Но и в обратную сторону, это тоже работает. Ведь не обязательно графику отрисовывать пиксель в пиксель с разрешением экрана, а можно брать например 0.75 от размера экрана и получившийся результат растягивать и т.д и т.п.
Так а зачем это всё тогда?
В целом, это исключительно теоретическое упражнение, чтобы понимать, что вы делаете и зачем. Подогнать ваши шейдеры цикл в цикл с производительностью GPU и рассчитать, что у вас будет 60 FPS, не выйдет. Зато можно понимать относительную “тяжесть” шейдера с развитием проекта или изменения в результате оптимизаций. Думать над тем, какие рендер фичи сделать опциональными, а какие по умолчанию и т.д.

Оптимизация производительности, это всегда про баланс.
Вот увидели вы, что расчет какого-либо параметра для рендера тяжелый и нагружает GPU. И, допустим, запекли все результаты расчетов в текстуру, которую передаете в шейдер. После этого обнаружили проблемы с memory bandwidth от того, что стали передавать на GPU больше данных. ОООок, выбрали какой-либо формат GPU компрессии, чтобы уменьшить размер передаваемых данных. Но теперь подрос размер билда т.к. до этого вы использовали png, которые почти не занимали места и т.д.
Вопрос всегда только в том, какой компромисс вас устраивает, его всегда придется искать.

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

Есть ли смысл от межстраничной рекламы, если ее почти всегда пропускают и редко по ней кликают?

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

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

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

Выглядит это обычно примерно так, как на скриншоте. Одна и та же игра, на одной и той же платформе.

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

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