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 | Поверх всего, отдельный pass | HUD, главное меню |
| 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-классы позволяют переиспользовать стили.
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 → …”.
Каждое изменение размера или позиции 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 работает.
Большой плюс 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’ы, без которых проект быстро превращается в неподдерживаемую кашу.