unity cull transparent mesh canvas что это

Меши (Meshes)

Meshes составляют большую часть создаваемых вами трёхмерных миров. Unity не имеет встроенных инструментов для моделирования геометрии, разве что за исключением некоторых плагинов Asset store. Но несмотря на это, Unity поддерживает работу со многими пакетами трёхмерной графики. Unity также поддерживает работу с мешами, которые состоят как из трёхсторонних, так и из четырёхсторонних полигонов. Неоднородные рациональные безье-сплайны (Nurbs), неоднородные рационально сглаживаемые сетки (Nurms) а также высокополигональные поверхности должны быть конвертированы в полигоны.

3D форматы

Импортирование мешей в Unity может быть выполнено с помощью двух основных типов файлов:

Любой из этих типов позволит вам добавлять свои меши в Unity, но есть соображения относительно того типа, который вы выберите:

Экспортированные 3D файлы

Преимущества:

Недостатки:

Собственные файлы 3D приложений

Преимущества:

Недостатки:

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

Текстуры

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

Textures в или над уровнем с компонентами (ассетами)»> Разместите свои текстуры в папке Textures в или над уровнем с компонентами (ассетами)

Создание и присвоение материала

Для каждого импортированного материала, Unity применит следующие правила:-

Если генерация материала отменена (иначе говоря если галочка Import Materials не выставлена), тогда будет назначен материал по-умолчанию. Если же генерация была включена, тогда произойдёт следующее:

Коллайдеры (Colliders)

Анимации (Animations)

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

Карты нормалей и персонажи (Normal mapping and characters)

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

Формы смешивания (Blendshapes)

Есть два способа импорта форм смешивания с нормалями:

Советы (Hints)

Редактор Unity отображает гораздо больше вершин и треугольников (по сравнению с тем, что отображается в моём трёхмерном приложении).

Так и есть. На что вы действительно должны обратить внимание, так это на то, какое количество вершин/треугольников на самом деле было послано для просчёта на графический процессор (GPU). В отличие от случаев, где материал требует, чтобы эти данные посылались на GPU дважды, такие вещи как твёрдые-нормали (hard-normals) и несмежные UV развёртки(non-contiguous UVs) намеренно отображают гораздо большее количество вершин/треугольников, чем есть на самом деле. В контексте UV и 3D пространства треугольники должны располагаться смежно, чтобы сформировать собой границу, поэтому при уменьшении количества треугольников на UV-швах, которые и должны были образовать собой границу и возникает эффект мнимого увеличения их количества.

Источник

Оптимизация 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 без кода

В этой статье ведущий UI/UX художник Никита Кандыбин и технический UI художник Ольга Кинчак поделятся эффективными базовыми практиками по оптимизации Unity UI, которые используются в компании Banzai Games при создании игровых интерфейсов, а также укажут на подводные камни тех или иных решений в дизайне и верстке. Практически во всех перечисленных ниже пунктах можно обойтись без кода, настраивая компоненты непосредственно в редакторе, а что-то даже предусматривая заранее на стадии проектирования макетов интерфейса.

Нативный Unity UI или, как его еще называют в народе, uGUI представляет собой довольно гибкий и удобный инструмент для создания и редактирования игровых пользовательских интерфейсов. Однако недостаток знаний, осведомленности о специфике работы и неправильное использование возможностей игрового движка рано или поздно приводит к возникновению проблем. Будь то низкая частота кадров, высокая загрузка центрального процессора, перегрев устройства и прочие страшные слова для проекта, который хочет стать (или продолжать оставаться) успешным.

Для мобильных платформ с их ограничениями по железу вопросы производительности и оптимизации становятся камнем преткновения на пути к реализации всего желаемого. Тем не менее это вовсе не повод отказываться от Unity UI — система хороша, просто нужно научиться в ней готовить.

Особенности Canvas

Для начала разберемся немного в том, каким образом организован Unity UI. Менеджментом всего, что связано с отрисовкой пользовательского интерфейса в Unity, занимается Canvas (далее просто “канвас”), являющийся родительским объектом для всех дочерних элементов интерфейса в иерархии сцены.

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

Перестроение происходит в несколько этапов: расчет положений объектов в лэйаутах, анализ оптимальных способов их отрисовки, применение масок и пересчет графики грязных объектов. Канвас формирует команды для рендера, которые движок Unity отправляет на GPU и в конечном счете визуализирует.

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

UI Kit на все случаи жизни

В процессе отрисовки макетов пользовательского интерфейса постепенно формируется UI Kit проекта — все разнообразие графических элементов (кнопок, панелей, фоновых изображений, арта, декора, иконок и т.д), а также правил их компоновки. В дальнейшем все эти элементы будут порезаны на ассеты, залиты в движок и станут конструктором для финальной сборки интерфейса игры. Очень важно заранее продумывать, что и в каком виде попадет в Unity и насколько ресурсоемким станет в итоге.

Использование в UI дизайне таких популярных методов как slicing, tiling и окрашивание является одним из наиболее эффективных и распространенных способов экономии и многократного переиспользования ресурсов проекта.

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

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

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

Overdraw

И в данном случае нюансами является специфика пайплайна рендеринга интерфейса в Unity и понятие overdraw. Если очень коротко, то overdraw — термин, обозначающий ситуацию, при которой один и тот же пиксель перерисовывается несколько раз (т.е. выполняется лишняя работа по его заполнению).

Читайте также:  какие расходы можно включать при усн доходы минус расходы 2020

Дело в том, что все элементы интерфейса в сцене Unity отрисовывает в Transparent по очереди, от самого дальнего к самому близкому, смешивая их цвета при прозрачности — по-умолчанию считая их прозрачными, даже если они таковыми и не являются. А это означает, что рендериться будут абсолютно все активные графические объекты в иерархии, независимо от того, загораживаются ли они визуально другими или нет. При этом большое количество перекрывающихся элементов может привести к чрезвычайному высокому количеству перерисовок пикселей, цвета которых нужно смешать, снижению скорости их заполнения (fill rate’a) и, как следствие, возникновению проблем с производительностью.

C помощью одноименного режима отображения “Overdraw” в редакторе Unity позволяет довольно удобно отслеживать такие вот узкие места и буквально видеть перерисовку в сцене. Пусть такая оптимизация на первый взгляд кажется довольно незначительной, но когда объектов на экране становится много (а в сложных интерфейсах их ОЧЕНЬ много) и все они начинают наслаиваться, даже такие мелочи могут дать существенный прирост к производительности.


В нижнем варианте реализации у кнопки FIGHT тень, подложка и рамка слиты в одну текстуру, в отличие от верхнего, где каждый из этих слоев является самостоятельным спрайтом. Идентичный визуальный результат — разный Overdraw.

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

Draw Calls и использование атласов

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

Один из наиболее эффективных способов снизить количество вызовов метода отрисовки заключается в использовании текстурных атласов — упаковки ваших текстур в единую, более крупную. Дело в том, что Unity старается автоматически объединять (“батчить”) графику в один draw call, отвечающую определенным критериям, тем самым ускоряя отрисовку кадра. В нашем случае наиболее важным здесь является то, что сбатчиться смогут только те объекты, которые используют одинаковые материалы и общий компонент рендерера (Canvas Renderer — дефолтный рендерер для всей UI графики). Таким образом, если элементы интерфейса в сцене используют стандартный UI материал, то, объединив их графику в один общий текстурный атлас, мы сможем получить тот самый желанный один draw call на рендеринг всей группы.

Однако и тут есть свои моменты. Как уже упоминалось ранее, объекты в кадре отрисовываются от самых дальних к самым близким, то есть от верхних к нижним в иерархии сцены. Если Rect Transform одного графического объекта хоть немного пересечется с другим, оба будут считаться накладывающимися друг на друга. При этом если в сцене между объектами, которые могли бы влезть в один draw call, ненароком вклинится объект с другим материалом, то он прервет объединение.

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


Отрисовка кадра. Объекты на экране появляются последовательно по иерархии, но неравномерно в связи с использованием разных материалов и прерыванием батчинга.

К преимуществам в использовании текстурных атласов можно отнести и то, что они позволят движку сжимать ассеты произвольных размеров, тем самым уменьшая их общий вес при хранении в памяти. Дело в том, что большинство алгоритмов сжатия требуют, чтобы размер текстур был кратен степени двойки (например, 128×128, 256×256, 512×512 и т.д). Атласы, являющиеся по-умолчанию таковыми, берут все вопросы по сжатию на себя, исключая необходимость подгонять всю исходную графику вашего интерфейса под вышеуказанный критерий.

Также при создании атласов очень важно руководствоваться не просто желанием удобно “складировать” ассеты, но делать это грамотно, эффективно, учитывая логику появления тех или иных элементов в интерфейсе вашей игры. Даже если на экране изображена всего одна малюсенькая иконочка размером в 16×16 пикселей, упакованная в атлас, в память устройства она потянет за собой всю его текстуру в 4К. Еще на этапе дизайна возможно прикинуть, какие элементы станут уникальными и для каких экранов, а какие будут являться сквозным конструктором для интерфейса игры.

Использование масок

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

Unity предлагает нам два по-разному работающих компонента из коробки на выбор: Mask и Rect Mask 2D. При использовании любого из них графика, вылезающая за пределы маски, все равно будет влиять на общий fill rate, хоть она и не отображается на экране. Поэтому старайтесь избегать ситуаций, в которых для достижения желаемого результата маской будет вырезан лишь небольшой участок крупного графического объекта. Возможно, в каких-то местах лучше не скупиться на ассеты и сохранить этот кусочек в виде отдельной картинки.

Что же касается влияния на draw calls, то здесь наши компоненты разнятся. Обе маски прерывают батчинг между замаскированными объектами и их не замаскированными соседями, но по разным причинам. Mask использует stencil буфер (буфер шаблона), создавая в рантайме другой материал для всех своих дочерних объектов. Из-за этого материала они не станут батчиться с другими элементами в сцене, но все еще смогут сбатчиться друг с другом и даже с другими такими же замаскированными объектами под другой Mask.

Rect Mask 2D материал не меняет, stencil не использует и дополнительный overdraw от графики маски не добавляет, что делает ее в сравнении более производительной. Тем не менее использование данного компонента все равно рвет батчинг, причем, в отличие от Mask, элементы интерфейса под разными Rect Mask 2D друг с другом батчиться уже не будут.

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

В Asset Store можно найти плагины, добавляющие функционал софт маски в редактор. Имея под рукой такой инструмент, ему сразу же находится повсеместное применение в дизайне — скроллы, анимации, визуальные эффекты, декор и т.д.


Все три варианта маскируют картинку, используя один общий исходный спрайт.

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

Работа с текстом

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

По умолчанию все шрифты, которые добавляются в Unity, отмечаются как динамические. При всем удобстве их использование имеет свою цену. Атлас динамического шрифта генерируется в рантайме и заполняется только используемыми на данный момент в текстовых компонентах сцены символами. Для каждого шрифта создается свой атлас, учитывающий все встречающиеся в сцене размеры текстовых символов. Каждое появление нового символа в интерфейсе инициирует обновление и перестройку атласа шрифта, что порой может негативно сказаться на производительности.

Читайте также:  аденомиоз регресс матки что это

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

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

Отдельного упоминания заслуживает функция Best Fit, позволяющая автоматически изменять размер шрифта, если текст не помещается в свой Rect Transform. Сами сотрудники Unity в официальных туториалах вспоминают ее с ужасом и не рекомендуют использовать — настолько все плохо, не оптимизировано и быстро перегружает шрифтовый атлас. Старайтесь заранее предусматривать максимально возможные размеры текстовых контейнеров и следить за тем, чтобы все везде помещалось, оставляя запас на все происки локализации.

Альтернативой UI Text может быть сторонний TextMesh Pro, который использует только статичные шрифты, да и его Best Fit работает гораздо лучше и экономнее. Однако минусом работы с данным компонентом может быть то, что под каждую локализацию и текстовый стиль придется создавать свой отдельный набор ассетов шрифтов. Тут уж каждый решает сам, что ему ближе и как удобней.

Размытие картинки (блюр) уже много лет как любят и используют в своей работе дизайнеры пользовательских интерфейсов, но в Unity UI его готовой оптимизированной реализации попросту нет.

Layout группы

Layout группы (Layout Groups) — крайне удобный инструмент в Unity UI, помогающий автоматически располагать произвольное количество элементов с заданой ориентацией, выравниванием и отступами. Однако использовать его нужно с осторожностью. Сортировка, поиск групп и расчет положений элементов при перерисовке атласа — довольно затратное дело, особенно если в сцене есть Layout группы, и тем более если они оказываются вложены друг в друга. Старайтесь всюду, где это возможно, обходится грамотным использованием анкоров и пивотов трансформа UI элементов, предпочитая их Layout группам.

Raycast Target

Галка Raycast Target на графических компонентах UI элементов означает, что последние могут отлавливать клики от пользовательской мыши или тапы на сенсорных экранах. Свежесозданному объекту с компонентами Image или Text редактор ставит эту галку по-умолчанию. Для того, чтобы определить, какой объект поймал “тычок” от пользователя, Graphic Raycaster, обрабатывающий события ввода в Unity UI, проходится по всему списку элементов в иерархии, помеченных как Raycast Target, и сортирует их очередность, рассчитывая пересечения и перекрытия одних объектов другими.

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

Иерархия. Чем проще — тем проще

И Layout группы, и Graphic Raycaster в процессе работы непрерывно путешествуют по дереву иерархии сцены, от находящихся глубоко дочерних элементов к самому корню, в процессе поиска различных компонентов.

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

Разделение канвасов

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

Казалось бы, вот оно — решение всех проблемы с ненужными перестроениями. Но у всего есть свои “но”. Контролировать большое количество канвасов может стать банально неудобно. Также очень важно помнить, что элементы принадлежащие разным канвасам гарантированно не будут батчиться друг с другом. Поэтому, принимая структурные решения, разделением элементов интерфейса на разные канвасы лучше пользоваться осторожно и обязательно проверять в Профилировщике (Profiler), действительно ли такой подход может дать заметный прирост к производительности.

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

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

Particle System

Тот, кто когда-нибудь пытался добавить в интерфейс системы частиц (Particle System), прекрасно знает, что это как смешивать жидкости разной плотности — одна обязательно будет отображаться над другой, как ты не крутись.

Стандартные частицы в Unity не учитывают сортировку объектов в канвасе и не умеют работать с масками. Поэтому на помощь опять приходят сторонние компоненты из Asset Store, которые решают вышеперечисленные вопросы, но при этом зачастую увеличивают ресурсную стоимость системы частиц. Следовательно, требования по производительности к частицам в пользовательском интерфейсе куда-более строгие, чем, скажем, на локациях или для персонажей. Кроме того, большое количество крупных наслаивающихся друг на друга частиц может значительно повысить overdraw.

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

Анимация

Рассмотрим частую ситуацию. Необходимо заанимировать кнопку и все ее стейты — Unity любезно предлагает нам Animation Controller (далее просто “аниматор”) с базовым суповым набором анимаций для разных состояний, которые останется только отредактировать, да еще и без необходимости запуска рантайма для проверки результата. Удобно? Очень удобно. И снова коварная дефолтная ловушка. Ведь каждый кадр аниматор будет перерисовывать этот объект, помечая как грязный, даже если на экране в данный момент вообще не проигрывается никакая анимация.

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


Пример анимации произвольного элемента интерфейса.


… и то, как данная анимация может быть реализована с помощью абсолютно разных подходов.

Пока не разошлись

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

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

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

Ребята в Unity, конечно, тоже не сидят сложа руки. Официальные гайды на Unity Learn пополняются хорошими статьями про оптимизацию UI, а новые версии движка потихоньку, но исправляют проблемы старых. Судя по последним анонсам, Unity уже готовят абсолютно новый унифицированный инструмент для редактирования пользовательских интерфейсов — на первый взгляд, очень уж напоминающий CSS для web-разработки. В новой системе обещают полностью переработать отрисовку интерфейса и значительно улучшить производительность. Что ж, посмотрим, что в итоге получится. А пока работаем с тем, что имеем.

Источник

Информ портал о технике и не только