Unity Term Book
动画与 UI

UI Systems

Unity 的 UI 技术栈涵盖经典 Unity UI(uGUI)与现代 UI Toolkit,以及 Canvas、CanvasScaler、EventSystem——构建菜单、HUD 与各类界面所需的核心工具。理解锚点布局、合批与事件流,能帮 UI 程序与设计师在多分辨率适配、运行时性能与可维护性之间做出正确选择。

想象一下...

Canvas 是挡在屏幕前的空白纸——所有 UI 元素都在上面。CanvasScaler 是尺子,分辨率变化(1080p 到手机)时缩放这张纸。EventSystem 是虚拟鼠标,决定点了哪个元素。三者缺一,UI 就会不显示、不缩放或不响应点击。

概念详解

Canvas 是所有 UI 的根容器。三种渲染模式: Screen Space - Overlay (始终在游戏之上,与相机无关)、 Screen Space - Camera (经特定相机渲染,受深度/后期影响),以及 World Space (场景中的 3D 对象——世界内屏幕、角色头顶血条)。

CanvasScaler 解决多分辨率。 Scale With Screen Size 是常用模式:在 Reference Resolution(1920×1080)下设计,scaler 适配真实屏幕。 Match(0=宽,1=高,0.5=平均)决定优先哪条轴。

EventSystem 是处理所有 UI 输入的单例:点击、触摸、手柄。 用 Raycaster(Canvas 上的 GraphicRaycaster,World Space 用 PhysicsRaycaster) 找悬停/选中元素。场景中必须 恰好一个 EventSystem——多了会冲突。

Unity 2021+ 起,UI Toolkit 是更新的栈,借鉴 Web 思路 (UXML 布局、USS 样式如 HTML/CSS)。复杂 UI 性能优于 uGUI,但与 3D 玩法集成更难。 游戏内运行时 UI 仍以 uGUI 更常见。

标准 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 始终叠在场景之上。HUD、背包、主菜单。不受摄像机影响。

Screen Space - Camera

通过指定 Camera 渲染。可对 UI 做后处理(blur、bloom)。

World Space

UI 是 3D 对象。血条、游戏内屏幕、VR UI。需要 EventSystem + camera raycast。

动手步骤

1

创建基础 Canvas

GameObject → UI → Canvas。Unity 会添加 Canvas + CanvasScaler + GraphicRaycaster + EventSystem。

2

配置 CanvasScaler

UI Scale Mode → Scale With Screen Size。Reference Resolution → 1920×1080(或你的目标)。Match → 0.5。

3

使用 RectTransform

UI 用 RectTransform 而非 Transform。Anchor 预设(右上、全屏拉伸…)是响应式布局的关键。

4

多 Canvas 设置 Sorting Order

Canvas → Sort Order:数字越大画在越上面。提示在背包之上,对话框在 HUD 之上。

5

拆分 Canvas 减少重批

每个 canvas 单独批处理。静态 UI(背景)放独立 Canvas,避免动态 UI 弄脏整批。

交互模拟器

观察 CanvasScaler——调整屏幕尺寸,看 UI 如何随之缩放。

HP 75/100
⭐ 1280

Game Menu

map

Scale: 1.00 | Reference: 1920×1080

代码示例

基础

用脚本更新 UI——血条、分数文字、显示/隐藏面板。

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)}";

      // Tint when HP is low
      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 while the menu is open
  }

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

代码示例

进阶

World Space UI——角色头顶血条,始终面向相机。

using UnityEngine;
using UnityEngine.UI;

// Attach to a World Space Canvas — HP bar over a character
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;

      // Follow the character + offset
      transform.position = target.position + offset;

      // Always face the camera (billboard)
      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;
      // Hide when HP is full
      gameObject.SetActive(current < max);
  }
}

📌 快速记忆

  • ▸Canvas Overlay:不受相机影响
  • ▸CanvasScaler:Scale With Screen Size → Reference 1920×1080
  • ▸场景中只能有 1 个 EventSystem——多了会出 bug
  • ▸拆分静态/动态 Canvas,避免昂贵的重批
  • ▸World Space UI 用 LateUpdate,以便在物理之后跟随

⚠️ 常见错误

  • ❌ Button 收不到点击

    缺少 EventSystem,或 GraphicRaycaster 被禁用

    ✅ 确保存在 EventSystem,且 Canvas 有 GraphicRaycaster

  • ❌ PC 与手机上 UI 观感不同

    CanvasScaler 未配置

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