~3 мин чтения

UI в 3D-игре — uGUI и UI Toolkit

Canvas, RectTransform, EventSystem — и две конкурирующие UI-системы.

В Unity 6 сосуществуют две UI-системы:

  • uGUI (Unity UI) — то, что Unity использовал годами. Через GameObject и Canvas.
  • UI Toolkit — новая система на UXML + USS (HTML + CSS аналогах). Для редактора уже стандарт, для runtime — стабильна и рекомендована для нового UI, но многие проекты всё ещё на uGUI.

Начнём с uGUI как с более распространённого, потом — UI Toolkit.

uGUI: Canvas и RectTransform

UI в uGUI живёт внутри Canvas — специального GameObject. Дочерние UI-элементы используют RectTransform (расширенный Transform с anchors, pivot и размером).

Три режима Canvas:

Render ModeГде рисуетсяКогда выбирать
Screen Space – OverlayПоверх всего, отдельный passHUD, главное меню
Screen Space – CameraПеред камерой, на заданной дистанцииЕсли UI должен попасть в постпроцесс
World SpaceВ 3D-сцене как обычный объектПолоска здоровья над врагом, экран компьютера в комнате

Anchors — основа респонсивности

Anchor — точка на родительском элементе, к которой “приклеена” сторона текущего. По сути — это аналог CSS position: absolute; top/left/right/bottom.

Если anchor min и max совпадают (например, обе в (0.5, 0.5) — центр), элемент имеет фиксированный размер. Если разнесены (min = (0, 0), max = (1, 1)) — элемент растягивается по всему родителю.

Веб

Flexbox/Grid делают разметку декларативно — описываете правила, браузер раскладывает. CSS-классы позволяют переиспользовать стили.

Unity

uGUI ближе к “absolute layouts с якорями”. Для flex-подобной раскладки есть компоненты: HorizontalLayoutGroup, VerticalLayoutGroup, GridLayoutGroup — но они императивно пересчитывают layout каждый кадр и могут быть медленными при большом количестве элементов.

Базовые компоненты uGUI

  • Image — картинка (sprite или solid color).
  • RawImage — texture без sprite-настроек.
  • TextMeshPro – Text (UI) — текст. Используйте TMP, не Legacy Text — TMP даёт SDF-шрифты с чётким масштабированием и нормальное форматирование (rich text, outline, gradient).
  • Button — кнопка с подсветками и onClick.
  • Toggle / Slider / InputField (TMP) — стандартные контролы.
  • ScrollRect — прокручиваемый контент.
  • Mask / RectMask2D — отсечение по форме.
public class HudController : MonoBehaviour
{
    [SerializeField] private TMPro.TextMeshProUGUI scoreText;
    [SerializeField] private UnityEngine.UI.Image healthBar;

    public void SetScore(int score) {
        scoreText.text = $"Очки: {score}";
    }

    public void SetHealth(float normalized) {
        healthBar.fillAmount = Mathf.Clamp01(normalized);
    }
}

EventSystem

Для работы кнопок и любого ввода в UI в сцене нужен EventSystem (один). Он маршрутизирует нажатия, наведения, тач-события на UI-элементы. Создаётся автоматически, когда вы добавляете Canvas через меню “GameObject → UI → …”.

Главный враг производительности uGUI

Каждое изменение размера или позиции UI-элемента помечает Canvas как “dirty” и пересобирает его меш. Анимация UI с большим количеством элементов на одном Canvas съест FPS. Разбивайте на несколько Canvas (один — статичный HUD, отдельный — анимированные числа урона), или используйте UI Toolkit.

UI Toolkit: UXML + USS

UI Toolkit живёт другими понятиями. Вы описываете дерево элементов в UXML (XML), стилизуете в USS (близко к CSS), и подключаете к сцене через компонент UIDocument.

<!-- HUD.uxml -->
<ui:UXML xmlns:ui="UnityEngine.UIElements">
  <ui:VisualElement class="hud">
    <ui:Label name="score" text="Очки: 0" class="score" />
    <ui:VisualElement name="healthbar" class="bar" />
  </ui:VisualElement>
</ui:UXML>
/* HUD.uss */
.hud { position: absolute; top: 16px; left: 16px; }
.score { color: white; font-size: 24px; }
.bar { width: 200px; height: 12px; background-color: red; border-radius: 6px; }
public class HudUI : MonoBehaviour
{
    private Label _scoreLabel;
    private VisualElement _healthBar;

    private void OnEnable() {
        var root = GetComponent<UIDocument>().rootVisualElement;
        _scoreLabel = root.Q<Label>("score");
        _healthBar  = root.Q<VisualElement>("healthbar");
    }

    public void SetScore(int score) => _scoreLabel.text = $"Очки: {score}";
    public void SetHealthNormalized(float n) {
        _healthBar.style.width = new Length(n * 100f, LengthUnit.Percent);
    }
}
Веб

Это буквально как браузерный UI: query-селекторы (root.Q<>("name")), USS-стили похожи на CSS, UXML — на HTML. Flexbox работает.

Unity

Большой плюс UI Toolkit — производительность (retained mode, не пересоздаёт меш на каждое изменение). Минус — World Space support появился только в Unity 6.2 как experimental, ещё не production-ready. До этого в World Space — только uGUI.

Что выбрать в новом проекте

  • HUD и in-game UI — UI Toolkit для большинства случаев, особенно если много меняющихся значений и сложные layout’ы.
  • Главное меню — любой подход; UI Toolkit удобнее, uGUI — если вам нужны визуальные эффекты (shaders, masks).
  • 3D-UI в мире (надписи над врагами, экраны на стенах) — uGUI в World Space (стабильно); либо UI Toolkit World Space с Unity 6.2 (experimental, готовится к стабилизации).

В следующей главе — Prefab’ы и ScriptableObject’ы, без которых проект быстро превращается в неподдерживаемую кашу.