Как стать автором
Обновить

UI-система для Unity. Надстройка над UI Toolkit

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров920

Привет. Я занимаюсь реализацией UI в нашей небольшой команде, разрабатывающей игры. Долгое время занимался 3D‑моделированием, моушн‑дизайном, UX/UI‑дизайном, построением дизайн‑систем. Позже жизнь привела меня в игровую индустрию, где я применил предыдущие навыки.

Команда разрабатывала гиперказуальные игры, и на момент моего присоединения к ней происходила перестройка — переход от гиперказуальных игр к хардкорным проектам. Тогда рассматривались два варианта новых проектов:

  1. Упрощённый — рогалик с хорошо проработанной системой боя.

  2. Более сложный — пошаговая сетевая стратегия с большим выбором карт и отрядов.

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

Когда возник вопрос работы над проектами, я решил глубже изучить рынок и состояние UI‑систем в играх. Так как команда работала только в Unity, я начал исследование именно в этой среде. К моему удивлению, оказалось, что весь игровой UI в самых популярных движках (Unity и Unreal Engine) находится в довольно зачаточном состоянии.

Например, UGUI от Unity — это слабо масштабируемая система, с помощью которой сложно создать адаптивный интерфейс. Кроме того, прототипировать интерфейс в современных инструментах, таких как Figma с библиотеками компонентов, Pixso (китайский аналог Figma), Storybook и других, совместно с UGUI практически невозможно. Но при этом многие разработчики Unity используют именно UGUI, так как это «родной» функционал Unity.

Тогда я решил посмотреть сторонние фреймворки, которыми пользуются крупные студии. Одним из таких примеров стал NoesisGUI — выглядело всё идеально: хорошее масштабирование, богатые возможности. Совместим как с Unity, так и с Unreal Engine.

НО! Есть одно «но»: NoesisGUI использует разметку WPF. А предполагалось, что всю работу над UI буду выполнять я один. При этом я не знал WPF вообще. Конечно, возможно было бы освоить его — ведь он похож на HTML/CSS, которыми я владел неплохо. Однако быстро собрать сложный интерфейс на WPF заняло бы много времени, а хотелось использовать уже привычные инструменты.

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

Ещё одним возможным решением стала система, которую Unity активно продвигала как замену UGUI — UI Toolkit. Именно она меня и заинтересовала.

UI Toolkit — это попытка воссоздать в Unity знакомую веб‑разработчикам связку HTML‑CSS‑JS, заменив её на UXML‑USS‑C#. По сути, они максимально приблизили логику к веб‑технологиям. Хотя функционал пока ещё не полностью дотягивает до CSS, подход очень близок к веб‑разработке. Интерфейс, собранный на UXML и USS, ведёт себя почти как HTML+CSS, и его можно легко прототипировать в Figma, а затем реализовать в Unity.

Для меня такой подход мог бы сильно ускорить разработку UI.

Решив попробовать эту систему, я сначала был доволен — ведь структура и атрибуты были мне знакомы. Однако вскоре радость прошла. Я привык работать с такими инструментами, как Vue.js или React, где можно создавать компоненты и иерархии компонентов.

В Unity есть базовый набор готовых компонентов — кнопки, чекбоксы, списки и т. д., но их внешний вид требует дополнительной настройки и доработки. Получается, что для каждого элемента нужно отдельно создавать файлы UXML (разметка), USS (стили) и C# (логика). И всё это нужно правильно связать между собой.

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

Кроме того, на тот момент я мог писать на JavaScript, использовал когда‑то jQuery или Vue.js, но с C# не работал давно и уже почти ничего не помнил.

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

SUS — Sharq UI System
(Sharq IT — наша компания, занимающаяся разработкой игровых проектов)

SUS — это внутренний инструмент для сборки UI‑компонентов.

Синтаксис SUS похож на подход Vue.js. Каждый компонент — это один файл, внутри которого полное его описание. Компоненты могут содержать в себе другие компоненты. Стандартный UXML использует теги начинающиеся на ui: Например <ui:VisualElement> или <ui:Button>. Мы реализовали вставку наших компонентов через sus: например как <sus:RadialProgressBar>
Используются три основных блока:

<template></template>

<script></script>

<style></style>

Примерная архитектура выглядит так:

Файл компонента парсится и все составляющие файла аккуратно складываются в JSON, который хранит иерархию содержания компонента и атрибуты. Дальше из JSONа собираются отдельные файлы UI — uxml, uss, cs, которые видны юнити.

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

Фактически, SUS — это обёртка с автосборкой над компонентами Unity UI Toolkit. То есть если мне нужно создать кнопку, я создаю новый компонент‑кнопку, внутри которого использую базовую кнопку UI Toolkit. В своём компоненте я могу переиспользовать её функционал, добавить нужную логику и применить собственные стили.

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

Таким образом, в дальнейшем планируется разделение компонентов на две категории:

  • Стандартные BuiltIn — используют базовые стили, цвета, иконки и шрифты.

  • Кастомные — адаптированы под конкретный проект.

Теперь, когда я создаю, например, прогресс‑бар, его можно легко переиспользовать в других проектах.

Реализована поддержка векторных иконок. Отдельным открытием для меня стало то, что в Unity до сих пор нет нормального встроенного инструмента для работы с SVG. Существует сторонний пакет, но он не предоставляет полного функционала. Например, если использовать нативный вектор (через этот пакет), то отрисовка происходит без сглаживания, и иконки выглядят «рваными».

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

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

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

Все компоненты в окончательном виде используются в одном файле верхнего уровня — SusApp.sharq. Этот файл выполняет роль, аналогичную App.vue во Vue.js: он служит центральным «хранилищем» всех возможных состояний интерфейса игры.

В SusApp.sharq создаются все экраны и оверлеи, а также определены слои для отображения тултипов (всплывающих подсказок). Управление этим файлом реализуется через класс UIManager, который является наследником MonoBehaviour.

SUS представляет собой часть автоматизации кода для реализации паттерна MVVM . В моём случае часть, о которой я рассказываю в этой статье, отвечает за реализацию View из этого паттерна. Более точно — файл SusApp.sharq и есть эта самая View.

Класс UIManager представляет собой половину ViewModel‑уровня. Вторая половина ViewModel реализована уже не мной, а программистом, который создал систему обсерверов. Эта система слушает события игровой логики. При наступлении таких событий генерируются собственные события, на которые подписан UIManager, который на разные события по‑разному управляет деревом VisualElementов (SusApp).

На сегодняшний день SUS живет в оном проекте и готовится переехать в другой проект. В первом проекте уже вполне можно прототипировать и реализовывать вот такие штуки:

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

Мой телеграм‑канал

Теги:
Хабы:
+5
Комментарии1

Публикации

Работа

Ближайшие события