Unity Term Book
Animation & UI

UI Systems

Hệ thống UI của Unity gồm Unity UI (uGUI) truyền thống và UI Toolkit hiện đại, cùng Canvas, CanvasScaler và EventSystem — công cụ cho menu, HUD và màn hình.

Hãy tưởng tượng...

Canvas là tờ giấy trắng đặt phía trước màn hình — mọi UI element đều nằm trên đó. CanvasScaler là thước đo giúp giấy tự co giãn khi màn hình thay đổi kích thước (từ 1080p xuống điện thoại). EventSystem là "tay chuột ảo" nhận input và quyết định element nào được click. Thiếu một trong ba sẽ dẫn đến UI không hiển thị, không scale đúng, hoặc không click được.

Khái niệm chi tiết

Canvas là root container cho toàn bộ UI. Có ba chế độ render: Screen Space - Overlay (UI luôn đè lên game, không bị camera ảnh hưởng), Screen Space - Camera (UI render qua camera cụ thể, có thể bị depth/post-processing ảnh hưởng), và World Space (UI là object 3D trong scene — dùng cho in-world screen, health bar trên đầu nhân vật).

CanvasScaler giải quyết vấn đề đa độ phân giải. Chế độ Scale With Screen Size là phổ biến nhất: bạn thiết kế ở Reference Resolution (1920×1080), CanvasScaler tự scale để UI vừa màn hình thực tế. Tham số Match (0=width-based, 1=height-based, 0.5=trung bình) kiểm soát chiều ưu tiên.

EventSystem là singleton xử lý toàn bộ input cho UI: chuột click, touch, gamepad navigation. Nó dùng Raycaster (GraphicRaycaster trên Canvas, PhysicsRaycaster cho World Space) để xác định element nào đang được hover/selected. Chỉ được có một EventSystem trong scene — nhiều hơn sẽ gây xung đột.

Từ Unity 2021+, UI Toolkit là hệ thống UI mới dựa trên web technologies (UXML layout, USS styling tương tự HTML/CSS). Hiệu năng tốt hơn uGUI cho UI phức tạp, nhưng tích hợp với game 3D phức tạp hơn. Hiện tại, uGUI vẫn là lựa chọn phổ biến cho game UI trong runtime.

Hierarchy chuẩn của Unity UI

uGUI (Scene Hierarchy)

📁 Canvas(+ CanvasScaler)

├ 📁 Panel

Image(background)

Text (TMP)

Button

Text (TMP)

└ 📁 HUD

Slider(health)

RawImage(minimap)

📁 EventSystem

Render Modes

Screen Space - Overlay

UI luôn đè lên scene. HUD, inventory, main menu. Không bị camera ảnh hưởng.

Screen Space - Camera

Render qua Camera cụ thể. Cho phép post-processing trên UI (blur, bloom).

World Space

UI là 3D object. Health bar, in-game screen, VR UI. Cần EventSystem + camera raycast.

Hướng dẫn thực hành

1

Tạo Canvas cơ bản

GameObject → UI → Canvas. Unity tự tạo Canvas + CanvasScaler + GraphicRaycaster + EventSystem.

2

Cấu hình CanvasScaler

UI Scale Mode → Scale With Screen Size. Reference Resolution → 1920×1080 (hoặc target). Match → 0.5.

3

Sử dụng RectTransform

UI dùng RectTransform thay vì Transform. Anchor preset (góc trên phải, trải dài toàn màn hình...) là chìa khoá responsive layout.

4

Đặt Sorting Order cho nhiều Canvas

Canvas → Sort Order: canvas có số cao hơn render trên. Dùng để tooltip luôn trên inventory, dialog trên HUD.

5

Tách Canvas để tối ưu rebatch

Mỗi canvas được batch riêng. Phần UI tĩnh (background) đặt Canvas riêng để tránh trigger rebatch khi UI động thay đổi.

Trình mô phỏng tương tác

Xem CanvasScaler hoạt động — thay đổi kích thước màn hình để thấy UI scale tương ứng.

HP 75/100
⭐ 1280

Game Menu

map

Scale: 1.00 | Reference: 1920×1080

Ví dụ Code

Cơ bản

Cập nhật UI elements từ script — health bar, score text, activate/deactivate panels.

using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class HUDController : MonoBehaviour
{
  [Header("Health")]
  public Slider healthSlider;
  public TMP_Text healthText;

  [Header("Score")]
  public TMP_Text scoreText;

  [Header("Panels")]
  public GameObject menuPanel;
  public GameObject hudPanel;

  public void UpdateHealth(float current, float max)
  {
      healthSlider.value = current / max;
      healthText.text = $"{Mathf.RoundToInt(current)}/{Mathf.RoundToInt(max)}";

      // Đổi màu khi HP thấp
      healthSlider.fillRect.GetComponent<Image>().color =
          current / max < 0.3f ? Color.red : Color.green;
  }

  public void ShowMenu(bool show)
  {
      menuPanel.SetActive(show);
      hudPanel.SetActive(!show);
      Time.timeScale = show ? 0f : 1f; // Pause khi mở menu
  }

  public void UpdateScore(int score)
  {
      scoreText.text = score.ToString("N0"); // "1,280" format
  }
}

Ví dụ Code

Nâng cao

World Space UI — health bar trên đầu nhân vật, luôn hướng về camera.

using UnityEngine;
using UnityEngine.UI;

// Gắn lên Canvas World Space — làm thanh HP trên đầu nhân vật
public class WorldSpaceHealthBar : MonoBehaviour
{
  public Slider slider;
  public Vector3 offset = new Vector3(0, 2.5f, 0);
  public Transform target;

  Camera cam;

  void Start() => cam = Camera.main;

  void LateUpdate()
  {
      if (target == null) return;

      // Theo dõi vị trí nhân vật + offset
      transform.position = target.position + offset;

      // Luôn nhìn về camera (billboard effect)
      transform.LookAt(transform.position + cam.transform.rotation * Vector3.forward,
                       cam.transform.rotation * Vector3.up);
  }

  public void SetHealth(float current, float max)
  {
      slider.value = current / max;
      // Ẩn khi HP đầy
      gameObject.SetActive(current < max);
  }
}

📌 Ghi nhớ nhanh

  • Canvas Overlay: không bị camera ảnh hưởng
  • CanvasScaler: Scale With Screen Size → Reference 1920×1080
  • Chỉ 1 EventSystem trong scene — nhiều hơn gây lỗi
  • Tách Canvas tĩnh/động để tránh rebatch tốn kém
  • LateUpdate cho World Space UI để follow sau physics

⚠️ Lỗi thường gặp

  • ❌ Button không click được

    Thiếu EventSystem, hoặc GraphicRaycaster bị disable

    ✅ Đảm bảo có EventSystem trong scene và Canvas có GraphicRaycaster

  • ❌ UI nhìn khác nhau trên máy tính và điện thoại

    CanvasScaler chưa được cấu hình đúng

    ✅ Scale With Screen Size + Reference 1920×1080 + Match 0.5