Что такое батчинг batching и для чего он нужен
Что такое батчинг биткоина и как он позволяет экономить?
Рекордный уровень транзакций, обработанных в сети биткоина за один день, составил 490 тысяч переводов. При этом стоимость в долларах оценивается миллиардами.
Средняя комиссия сети в первый пик, который состоялся в мае 2017 года, вырос до доллара. И их стоимость продолжает подниматься: к началу июня средние сборы пробили уровень в 5,5 долларов. Это уже было шоком, потому что за три года до этого комиссия не поднималась выше 31 цента. В этот момент появилось решение, которое смогло сократить количество транзакций.
В самые загруженные для сети дни, пользователи обнаруживают, что комиссия будет больше, чем сумма перевода. И это фатально для принятия биткоина как платежной системы.
Таким образом, появляется батчинг.
Батчинг — это объединение многих выходов в одну транзакцию.
Дэвид А. Хардинг, автор биткоин-документации, опубликовал сообщение в блоге: экономии средств на батчинге достигает 80%.
Идея была простой — для входов, отправляющих сразу несколько транзакций, выходы кластеризуются в одну транзакцию. Это становится более экономичным. Дэвид обнаружил, что если комбинировать 10 транзакций в одну, а не отправлять их по отдельности, сохраняется 75% площади блока.
По сути, пакетная обработка, батчинг — это один из способов собрать как можно больше транзакций в ограниченное пространство блоков, доступное на блокчейне биткоина.
Когда начала расти популярность криптовалют в середине 2017 года, пользователи начали более тщательно изучать, насколько эффективно они используют пространство блоков. В целом, 2 Мб места использовалось неэффективно. Началась неформальная кампания: объединять переводы и экономить пространство. Некоторые биржи проводили такую политику в течение многих лет, другие внедрили ее. Вопрос был исчерпан из-за того, что цена BTC упала в первом квартале 2018 года, а транзакционная нагрузка и, следовательно, средняя комиссия, снизилась.
Сейчас пакетные платежи все еще используются, несмотря на низкое количество транзакций.
Где искать статистику
Есть некоторые сайты, например, transactionfee.info и outputs.today.
Они отслеживают именно выходы, которые являются лучшим показателем общей экономической активности на блокчейне, чем транзакции за день. Поскольку одна транзакция может включать в себя несколько выходов, количество итоговых выходов более важно. Крупные участники сети используют пакетную обработку для уменьшения общей суммы транзакций.
Матчасть
Биткоин использует модель UTXO, которая означает Unspent Transaction Output — выходы неизрасходованных транзакции. Для сравнения, Ripple и Ethereum используют модель «счет/баланс». В сети BTC пользователь не имеет баланса, а только UTXO, которыми управляет.
Если кто-то хочет перевести деньги кому-то другому, кошелек выбирает один или несколько выходов. То есть, набирается сумма, которую нужно отправить. Затем эта сумма переходит к получателю — это выход (для кошелька-отправителя), а разница возвращается к отправителю, что называется выходом изменения. Каждый выход может иметь практически неограниченное количество значений в виде сатоши.
Чтобы лучше понять, представьте бумажник с разными купюрами. Вам выставили счет за кофе в 250 рублей, вы подаете 300 и ожидаете сдачу. Ситуация в бумажнике меняется? Вы не отрезаете от сотни половину, а получаете возврат переплаты.
Также нужно помнить, что нет жесткого ограничения на количество транзакций, которые могут вписываться в блок. Есть ограничение на размер в мегабайтах (пока 2 Мб). Большие транзакции (в размере, а не сумме перевода) будут платить более высокие комиссии, чтобы попасть в блок. Кроме того, каждая транзакция может иметь практически неограниченное количество входов или выходов.
Каждая транзакция имеет хотя бы один вход и выход, но по факту больше. Большая часть этого пространства занята вводом (часто 60% и более из-за подписи, которая доказывает, что BTC принадлежат отправителю), в то время как выходные данные составляют 15-30%. Чтобы сохранить вес транзакции есть два основных варианта:
Это преимущество BTC как платежной системы. Транзакция может объединить тысячи отдельных переводов.
Пакетная транзакция в самом общем варианте определяется как «транзакция с тремя и более выходами». Как правило, батчинг осуществляется в основном пулами или биржами, которым важная такая эффективность. Редко, чтобы обычный пользователь занимался созданием пакетных транзакций, тем более, в кошельках часто нет такого интерфейса, а в повседневной жизни это нужно редко.
И несмотря на то, что в обычной рутине это не пригодится, важно понимать эту особенность сети. Это позволяет справедливее оценить, насколько используется сеть.
Это как подсчитать пассажиропоток: мы считаем вместимость автобуса, чтобы понять, сколько людей ездит по маршруту, а не количество транспортных средств.
Как Segwit, так и пакетные операции созданы для сжатия транзакций, чтобы поместить их в доступное пространство блока. Их используют Binance, Bitfinex и Shapeshift.
Есть заблуждение, что количество транзакций упало из-за батчинга, но это не так. Он пока занимает не такую большую долю, хотя есть восходящий тренд. Но при этом в них передается до 70% всех BTC.
Количество платежей упало примерно настолько же, насколько и количество транзакций.
Тем не менее, все это говорит, что биткоин может масштабироваться собственными средствами: осилить дополнительную нагрузку до определенного момента.
Как совершать батчинг-транзакции
В полной ноде Bitcoin Core или других узлах с аналогичным API вместо sendtoaddress, например:
sendtoaddress 1FjdYJTkdmA2KYvGqRX3G3WJeTFABgUJsJ 1.23
sendtoaddress 194hTHKyJchh6dV8a5Ce5Jd1ENEaxMyKUK 4.56
Собственно, в обычной жизни это можно использовать так: просто «накопить момент», когда нужно сделать сразу несколько переводов. Отложить несколько покупок, броню билетов и т.д. на один день.Это делается через кнопку Add Recipient.
Оптимизация Unity UI
В этой статье разбираются вопросы оптимизации UI-элементов проектов, сделанных в Unity. На основании информации из официальной документации и личного опыта я постарался наглядно объяснить принципы работы UI-элементов. Также здесь вы найдёте практические советы, которые помогут улучшить производительность вашего проекта в том, что касается пользовательского интерфейса.
Терминология
UI-элементы — все элементы в Unity, относящиеся к построению пользовательского интерфейса. Сюда относятся, например: кнопка, текст, картинка, выпадающее меню и др.
Холст (canvas) — базовый элемент UI, являющийся контейнером для остальных элементов.
Меш (mesh) — совокупность параметров описывающих 3D-модели.
Квад (quad) — это меш, который представляет из себя четырехугольник.
Батчинг (batching) — объединение мешей объектов в один большой меш для более быстрой отрисовки.
Вызов отрисовки (draw-call) — команда на отрисовку от движка к графическому API (например, OpenGL или Direct3D).
Transparent queue — очередь отрисовки прозрачных объектов.
Альфа-смешивание (Alpha blending) — алгоритм смешивания пикселей по альфа-каналу для получения изображения с прозрачностью.
Атлас (Atlas) — вид ресурсов, который объединяет несколько текстур в одну.
Вводная
В оптимизация UI нет универсальных правил, работающих в любой ситуации. Всё сводится к нахождению баланса между стоимостью батчинга и количеством вызовов отрисовки. Можно выделить четыре основные проблемы:
Отрисовка Unity UI
Базовым элементом пользовательского интерфейса Unity является холст. Он отвечает за генерацию, сортировку и отрисовку мешей дочерних элементов интерфейса. Все элементы UI должны быть дочерними к какому либо холсту, в противном случае они не будут отображаться в игре.
Отрисовка происходит от самого дальнего к самому ближнему объекту от камеры (back-to-front) в Transparent queue с альфа-смешиванием.
Отдельно надо отметить, что прозрачность UI элементов НЕ влияет на производительность. Даже если элемент полностью состоит из “непрозрачных” пикселей, он все равно будет отрисован с использованием альфа-смешивания.
Также важно понимать, что при отрисовке обрабатываются все пиксели всех активных элементов. Это не зависит от того, видны они, перекрыты другими объектами или вообще полностью прозрачны.
Перестроение интерфейса пользователя
Перестроение интерфейса пользователя — это многоэтапный процесс, включающий в себя построение мешей каждого элемента UI, и попытка батчинга этих мешей для того, чтобы минимизировать количество отрисовок (draw calls).
Перестроение происходит в четыре этапа:
Перестроенный холст кешируется и переиспользуется до тех пор, пока один из элементов в холсте не помечается как изменённый.
Изменёнными (dirty) помечаются объекты, которые были активированы или деактивированы; у которых изменился материал, позиция, масштаб, поворот; изменилось текстовое значение у текстового компонента; производилось переназначение родителя и т.д.
В этом случае заново происходит перестроение холста, содержащего хотя бы один изменённый элемент. Правда, это относится только к тому холсту, в котором находится элемент. То есть изменения элементов в дочерних холстах не влияют на родительские.
Чем больше элементов в холсте, тем больше будут издержки на анализ и сортировку объектов.
Батчинг мешей
Объединение мешей, или батчинг, помогает снизить нагрузку на GPU, уменьшая количество вызовов отрисовки. В процессе батчинга меши сортируются по глубине и проверяются на перекрытие. При проходе от дальнего элемента к ближнему (или от верхнего элемента к нижнему в иерархии) в рамках одного холста объекты с одинаковыми материалами или текстурами объединяются в один меш. Для этого между ними не должно быть объектов с иными материалами. Также объекты с иными материалами не должны перекрывать запекаемые объекты своими габаритными контейнерами. Операция батчинга мультипоточная, её производительность значительно разнится в зависимости от количества ядер у процессора.
Текст может батчиться с другим текстом, если у них один и тот же шрифт. При этом неважно, выбраны одинаковые или разные настройки размера шрифта и стили. Если же шрифты разные, то текст не будет батчиться.
Также надо учитывать, что текст может перекрыть объект своим габаритным контейнером, и такое перекрытие можно легко пропустить.
Рассмотрим пример. Есть три объекта A, B и C, расположенные в иерархии таким образом:
На изображении слева объекты A и C будут объединены, т.к. имеют один и тот же материал и не пересекаются с объектом B. На изображении справа объекты A и C не будут объединены, т.к. имеется пересечение с объектом B.
Общие советы по оптимизации UI
Прежде чем начинать оптимизацию, настоятельно рекомендуется провести профайлинг UI. Это поможет определить узкие места, приводящие к потере производительности (если они есть). Для профайлинга существует множество инструментов, как встроенных в Unity (Unity Profiler), так и сторонних. Но вопросы профайлинга UI в этой статье мы разбирать не будем.
Вот что можно посоветовать для оптимизации UI в Unity:
Raycast Target у компонента изображения.
У TextMeshPro он спрятан во вкладке Extra Settings.
Элементы проходят проверку, когда:
Также имеет смысл убирать флаг Raycast Target с дочерних элементов, если корневой объект уже имеет его и полностью перекрывает своей геометрией дочерние элементы. Например, стандартная кнопка Unity UI.
Изображение своей формой полностью перекрывает текст, в этом случае можно снять Raycast Target с компонента текста.
Если все элементы холста не ждут событий ввода, то можно удалить компонент Graphic Raycaster с холста/вложенного холста.
Работа с текстом и его оптимизация
Текст в интерфейсе Unity состоит из сеток, в которых на каждый символ создаётся свой квад (quad). Меш перестраивается каждый раз, когда изменяется значение текста. Также перестроение происходит, если был выключен и повторно включён текстовый компонент или его родитель.
По умолчанию шрифты в Unity добавляются как динамические. Для каждого динамического шрифта, используемого в текстовом компоненте на сцене, создаётся свой атлас. В этот атлас включаются только используемые символы. Например, если текстовое поле содержит текст “New Text”, то созданный для него атлас будет содержать символы “N”, ”e”, “w”, “T”, “x” и “t”. Для каждого символа, отличающегося по размеру или стилю, будет создано своё представление в атласе.
Если в процессе выполнения программы содержимое текстового компонента изменится и там появятся символы, которые отсутствуют в атласе, будет вызвана перестройка всего атласа. В случае, если в текстуре атласа есть свободное место, то необходимые символы будут просто добавлены туда. При этом символы, которые в данный момент не используются, не удалятся. Если в атласе недостаточно места для новых символов, его размер будет удвоен и заполнен заново на основе используемых символов в активных текстовых компонентах.
Если для проекта задано строго определённое количество символов, например только латинский алфавит, то стоит использовать статичные шрифты, которые хранятся в памяти постоянно. Если в вашем проекте допускается большое количество символов, то лучше всё же остановиться на динамических шрифтах.
Можно также повысить производительность, если заменить текстовый компонент на спрайт. Например, появляющиеся в игре цифры (счёт) можно сделать, используя спрайты из одного атласа, содержащего набор только необходимых символов. В этом случае не будет издержек на перестроение холста и атласа шрифта.
Использование резервных шрифтов (Fallback fonts), перечисленных в поле Font Names в настройках шрифта, приводит к увеличению используемой памяти. Особенно это заметно на пиктографических шрифтах.
Не рекомендуется использовать Best Fit, т.к. эта опция приводит к быстрому переполнению атласа и вызывает его перестройку.
Best fit игнорирует настройки размера шрифта и пытается уместить текст в габаритный прямоугольник текстового компонента.
Теперь пара слов о TextMeshPro (TMP), популярной замене стандартному текстовому компоненту Unity. TextMeshPro также перестраивает свою сетку каждый раз, когда значение текста меняется. Однако TMP-текст не использует динамические шрифты. Для него заранее генерируются атласы шрифтов, в которые включаются все необходимые символы. Если для какого-то текста на сцене нет символа в назначенном на его компонент шрифте, то TMP начинает искать в резервных шрифтах. Если и там ничего не находится, то TMP будет пытаться найти этот символ во всех загруженных шрифтах.
Best Fit в TMP не создаёт проблем, как обычный текстовый компонент, так что его вполне можно использовать.
Большое количество шрифтов с разными локализациями или большие атласы шрифтов могут занимать много памяти. Поэтому лучше использовать предварительную загрузку только необходимых для конкретной локализации шрифтов.
В World Space рекомендуется использовать TextMeshPro вместо TextMeshProUGUI.
TextMeshProUGUI используется в холстах.
Атласы Спрайтов
Спрайтовые атласы — это вид ресурсов, который объединяет несколько текстур в одну. Они позволяют снизить количество отрисовок (draw calls) и повысить производительность.
Создание атласа.
Создаём атлас: Asset > Create > Sprite Atlas.
Выделяем атлас и помещаем необходимые sprite в Objects for Packing.
Нажимаем Pack Preview для предпросмотра атласа.
Нужно учитывать, что даже если на сцене используется один или несколько спрайтов из атласа, то атлас всё равно будет загружен целиком. Поэтому нет смысла пытаться внедрить все изображения в один гигантский атлас, который на устройствах с небольшой оперативной памятью может занять её ощутимую часть. Лучше разбить на какие-то более мелкие атласы, например на атлас пользовательского интерфейса меню игры и атлас интерфейса игрового режима.
Избегайте больших пустых мест в атласе, чтобы не занимать лишнее место в памяти. Для этого можно изменить размер атласа или добавить дополнительные изображения, чтобы максимально заполнить пустое пространство.
Для изображений, которые не попали в атлас, необходимо выбрать правильные настройки.
К каждому формату сжатия имеются требования, при соблюдении которых оно будет эффективно работать. Самые частые требования к изображениям:
При выборе формата сжатия Unity подскажет, если какие-то требования для выбранного формата не будут выполнены.
Также не забывайте, что форматы отличаются от целевого устройства. Дополнительную информацию и рекомендации по форматам можно посмотреть в официальной документации:
Оптимизация игры на Unity и dev story Tap Tap Builder
В копилке каждого инди-разработчика должен быть свой сити-билдер, может быть поэтому я решился «сконструировать» свой велосипед. Конечно же, с квадратными колесами и креслом-качалкой вместо седушки. Работаю я один, поэтому никаких дизайнеров, художников, и тем более моделлеров, в проекте нет. Кроме того, в общем-то, это моя первая игра с трехмерной графикой. Дабы не утруждать себя изучением продвинутых инструментов для создания трехмерных моделей, я решил все сделать своими руками и средствами игровой среды Unity. Там есть только примитивы, вроде кубов да цилиндров, а также возможность их раскрасить. Что ж, следовало запастись терпением и начать «творить», погрузившись в роль архитектора. Полезной информацией для начинающих инди-разработчиков может оказаться мой опыт работы с издателем, а также способы оптимизации игры.
Об игре
Основной особенностью Tap Tap Builder является симбиоз с кликером, а сей жанр крепко обосновался среди широкой публики. Итак, для возведения зданий от игрока потребуется, помимо некоторого количества ресурсов, изрядно понабивать пальцы, жмакая по экрану. Правда, можно построить строительный кран, который будет строить за вас, но весьма медленно. Большинство зданий можно улучшать, при этом через каждые 5 уровней изменяется их модель. Каждое здание в игре играет свою определенную роль.
В жилых домах живут люди. Без них население города расти не будет. Когда горожане обзаводятся жильем, они начинают искать работу. Например, могу пойти работать в офис. Офисы — основной источник поступления кредитов в городской бюджет в виде налогов. Кто-то может пойти работать за завод. Заводы производят ресурсы — металл и бетон. Для работы всех зданий нужна электроэнергия. Для этого придется построить электростанцию. Кроме того, в некоторых зданиях можно работать самому, при этом будет расходоваться энергия игрока, которая восстанавливается со временем. К примеру, игроку не хватает металла. Вместо того, чтобы ждать пару часов, пока он будет производиться на заводе, игрок может перейти в здание завода и поработать там сам. И конечно же, суть работы заключается в том, чтобы 100 раз кликнуть по кнопке с надписью «Работать»)
Если жители не смогут найти работу, придется платить им пособие по безработице. Однако, если же работников будет не хватать, то здания будут работать неэффективно. Поэтому важно постоянно следить за балансом рабочих мест и количеством жителей.
Зданий в игре довольно много. Есть отели и рестораны, полицейские участки и пожарные станции, банки, фитнес центры, биржы и т.д. За строительство и улучшение зданий игрок получает опыт и может повысить уровень города. При этом он получает 1 золотой ключ, который понадобится при строительстве специальных построек. Что-то вроде очков умения в RPG. Например, можно построить банк, тогда при выходе из игры все накопленные средства будут перечисляться на депозит, а игрок будет получать проценты за все время отсутствия в игре. Или можно построить налоговую инспекцию, которая увеличивает поступление налогов в городской бюджет на 10%. Кроме основных и специальных построек, есть еще служебные, уникальные и декоративные.
Транспорт
Еще в городе есть транспортные средства. Сделаны они только для красоты. Если построить городскую администрацию, по городу начнут ездить лимузины. Можно также построить шоу-рум, тогда по городу начнут гонять спорткары.
Взаимодействие игроков
Среди служебных построек есть пивной паб и почта. Построив их, игроки смогут взаимодействовать друг с другом, например, обмениваться инвайтами и ресурсами. При этом не нужен доступ в сеть. Игроки будут обмениваться бит-кодами, это что-то вроде промо-кодов или купонов. Каждый город имеет уникальный индекс, который отображается в здании почты. Его нужно указывать в качестве получателя при отправке посылки. Кроме того, конечно же, нужно будет выбрать, что отправить. Например, можно отправить 1000 единиц металла, а полученный код надо будет сообщить другу. При этом этот код не получится отправить нескольким игрокам, поскольку в нем зашифрован индекс получателя.
Похожим образом генерируются промо-коды, которые вставляются в сообщения на стену в социальных сетях.
Насколько удачно это решение, покажет время. Буду надеяться, что игроки оценят оригинальную идею.
Участие в Games Jam
Проект успел принять участие в Games Jam Kanobu 2016 и оказаться в подборке интересных проектов. Увы, до финала не дошел. Зато удалось пообщаться с другими разработчиками и получить полезные отзывы. К сожалению, реальных игроков на таких мероприятиях практически не бывает. Но самое главное, игра наша издателя. Им стала российская компания Herocraft. И это круто! Кроме того, было еще 2 предложения, обсуждение которых закончилось без результата.
Итак, вкратце поделюсь поделюсь своими советами по поводу хакатонов (hackathon) и джемов (jam):
— ищите команду. Вероятность найти команду на хакатонах невелика. Обычно участвуют уже сформированные команды, а свободные художники на хакатоны заглядывают крайне редко. Пробуйте, но не рассчитывайте;
— смотрите на другие проекты и их результаты. Определяйте для себя наиболее популярные направления в разработке и «заимствуйте» хорошие идеи);
— ищите отзывы об игре;
— ищите издателя;
Опыт работы с издателем
Первым делом составляется договор, в котором оговариваются платформы для выпуска игры, юридические и финансовые вопросы. До подписания договора стоит подготовить список вопросов и получить на них ответы. Например:
— какие доработки потребуются?
— на сколько может растянуться процесс доработок?
— какие условия расторжения договора?
После этого начинается процесс доработки игры. Издатель составляет список задач, которые нужно выполнить. Советую сразу определиться с удобной системой управления проектом. В моем случае это был GitHub. Там можно хранить исходники игры, билды и прочие файлы, а также заводить задачи и баги.
Касательно Tap Tap Builder основными задачами оказались:
— доработка системы обучения
— улучшение интерфейса
— интеграция инструментов аналитики
— увеличение производительности игры
— создание контента для игровых магазинов (иконка, баннер, описание, скриншоты, видео)
— разработка тестов
Замечу, что многие подзадачи пришлось отложить до релиза ввиду трудоемкости их выполнения. На этапе разработки тестов проходит итерация тестирования на стороне разработчика, ведь все переданные тесты должны быть как минимум корректными.
После доработки игры начинается итерация тестирования на стороне издателя и исправление обнаруженных багов.
И вот доведенный до кондиции и отлежавшийся билд отправляется на софтланч (soft launch). Софтланч это ограниченная публикация игры, например в какой-то одной стране и на одной платформе. Задача софтланча — получить отзывы реальных игроков и определить основные метрики игры (доход, удержание и прочие). На основе этих данных принимается решение о целесообразности мирового релиза. В случае провала софтланча, контракт расторгается, игру возвращают разработчику, и он может самостоятельно опубликовать ее.
Оптимизация игры
Первые попытки запустить игру на мобильных устройствах выявили существенные проблемы с производительностью. Игра показывала 10-15 FPS на пустом острове, при этом устройства были далеко не самые слабые (Sony Z1 и Asus Transformer). Последующая терапия позволила увеличить скорость игры в несколько раз. Итак, по порядку.
Оптимизация скриптов
Не стоит лихорадочно начинать искать проблемы в игре и оптимизировать наиболее вероятные узкие места. Первым делом надо запустить Profiler (доступен в бесплатной версии Unity 5).
У меня сразу же обнаружились проблемы в скриптах. Исправление не заняло много времени, вся оптимизация свелась к кешированию информации и сокращению количества вызовов. Кстати, рекомендую шаблон проектирования Memoizer. Суть его состоит в запоминании результата работы функции для последующих вызовов с идентичными параметрами. Параметрами могут быть не только простые типы, но и структуры и классы. Ниже приведу пример использования этого шаблона.
Оптимизация трехмерных моделей
После того, как проблема со скриптами была решена, пришло время заняться рендерингом (rendering). Значительное влияние на производительность оказывал тот факт, что модели зданий были сделаны из примитивов, которые имели разные материалы (и цвета). Статистика показывала около 600 draw call (после работы автобатчинга) и 100.000 треугольников. Для сравнения — на текущий момент для сферической игры в вакууме рекомендуется иметь до 100 draw call и до 30.000 треугольников.
Первое решение — уменьшение количества поверхностей. Пришлось импортировать ассет для редактирования мешей. Многие здания содержали цилиндры, а стандартный цилиндр имеет 20 граней и 80 треугольников. Упрощение геометрии цилиндров до 12 граней дало ощутимый эффект в ущерб небольшой угловатости зданий.
Следующий шаг — удаление невидимых граней из примитивов. В результате существенное сокращение общего количества треугольников (около 20%) никакого прироста FPS не принесло. Вероятно, движок и так не тратит ресурсы на отрисовку невидимой геометрии, даже если она находится в пределах видимости камеры. Итог — бесполезный шаг.
Батчинг (batching)
Следующий шаг — попытка использования статического батчинга (batching). Вкратце расскажу про батчинг, для тех, кто не в курсе. Батчинг — это группировка мешей (mesh) в 1 общий меш перед вызовом перерисовки (draw call). Просто так получается, что видеокарте проще нарисовать 1 объект сразу, чем по частям за несколько вызовов. При этом есть несколько нюансов. Объединение возможно только для мешей, которые использую один материал. Во вторых, суммарное количество вершин в общем не должно превышать 900. И в третьих, изменение transform (позиция, поворот и масштаб) дочерних объектов невозможно. К примеру, у «сбатченой» модели автомобиля не будут крутиться колеса. Батчинг бывает статический и динамический. Динамический батчинг работает во время выполнения и не требует никаких действий со стороны разработчика. Результат работы динамического батчинга можно увидеть в окне Statistics.
Статический батчинг можно реализовать двумя способами — поставить галочку Static для объекта на сцене или префаба (prefab). Это могут быть статические игровые объекты, например элементы ландшафта, растительность и здания. Второй способ — использование StaticBatchingUtility во время выполнения.
Вполне логично было выполнить статический батчинг для зданий, что я и сделал. В результате игра стала работать еще медленнее! Как оказалось, принудительный статический батчинг нарушает работу динамического батчинга, который работает эффективнее и группирует мешы из разных логических объектов, например, принадлежащие разным зданиям. Кроме того, автоматически сгруппированные объекты могут двигаться относительно друг друга (при этом группировка отменяется). Итог — применение статического батчинга может быть полезно только при глубоком понимании логики его работы.
Оптимизация теней
Следующее наблюдение — отключение динамических теней сокращает количество треугольников ровно в 2 раза, что давало прирост FPS около 20%. Изменение качества теней видимого эффекта не дало. В данной ситуации есть простое стандартное решение — замена теней спрайтами. Такие тени часто называют статическими. Сразу же возникает вопрос — как получить тени объектов, ведь не рисовать же их вручную?! Самое простое решение — использовать размытые окружности. Это подошло бы для теней персонажей в простом раннере или стрелялке. Мне такое решение не подошло — тени должны повторять геометрию зданий. Что же, пришлось написать скрипт для дампа (dump) теней. Алгоритм работы простой — скрипт по очереди создает здания (из prefab) и делает скриншот здания с тенью, сохраняя его на диск. Затем второй скрипт производит элементарную обработку полученных изображений, выполняя заливку тени черным цветом и удаляя фон (по цвету). Увы, готовых решений я не нашел, поделитесь своим опытом в комментариях.
Итог — увеличение скорости на 20% при появлении незначительных артефактов (при наложении и наслоении теней). Кстати, спрайтам с тенями нужно установить Packing Tag, например, Shadow. Тогда Unity создаст для них атлас (atlas), и отрисовка ВСЕХ теней будет выполняться за 1 draw call. И еще одно замечание — на некоторых устройствах возможны проблемы с отображение динамических теней, так что замена их на статические тени позволит избежать проблем.
Дальнейшая оптимизация трехмерных моделей
К сожалению, результат проведенной оптимизации оказался неудовлетворительным — игра показывала 20-25 FPS на мощном устройстве. Я решился на написание еще одного скрипта для запекания (bake) моделей. Суть в том, чтобы сгенерировать новый mesh и наложить на него текстуру для раскраски зданий. Текстура представляет собой простую палитру цветов размером 8х8, которая умеет автоматически заполняться при появлении новых материалов (цветов). При этом необходимо сформировать корректную UV-развертку (UV-mapping). На Asset Store есть плагины для запекания объектов, но они не умели генерировать текстуру по цветам материалов. Не буду подробно останавливаться на деталях реализации, т.к. понимаю, что моя ситуация довольно специфичная. Хотя с другой стороны, этот метод может найти применение в популярной ныне воксельной (voxel) графике. Ведь делать прототипы моделей в Unity гораздо удобнее, чем изучать моделирование. Если конечно, у вас в команде, нет моделлера, как у меня. У меня вообще никого не было).
Конечный результат превзошел все ожидания — скорость игры увеличилась в разы. Игра показывает 50-60 FPS на огромном городе. Дальнейшая оптимизация не требуется.
Заключение
Прошу прощения за то, что статья оказалась весьма большой. Ведь хотелось и про игру рассказать, и опытом поделиться. И напоследок мой совет — делайте классные прототипы и не тратьте силы на оптимизацию игры до появления рабочей версии.
Буду рад услышать ваши советы по оптимизации в комментариях, а также готов ответить на вопросы!