
Привет. Я занимаюсь реализацией UI в нашей небольшой команде, разрабатывающей игры. Долгое время занимался 3D‑моделированием, моушн‑дизайном, UX/UI‑дизайном, построением дизайн‑систем. Позже жизнь привела меня в игровую индустрию, где я применил предыдущие навыки.
Команда разрабатывала гиперказуальные игры, и на момент моего присоединения к ней происходила перестройка — переход от гиперказуальных игр к хардкорным проектам. Тогда рассматривались два варианта новых проектов:
Упрощённый — рогалик с хорошо проработанной системой боя.
Более сложный — пошаговая сетевая стратегия с большим выбором карт и отрядов.
После работы над гиперказуальными играми команда плохо представляла себе, что такое полноценная игра как продукт, и не видела проблем с 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 живет в оном проекте и готовится переехать в другой проект. В первом проекте уже вполне можно прототипировать и реализовывать вот такие штуки:



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