11.1 Canvas 与 EventSystem
Canvas
Canvas 是所有 UI 元素的容器。创建 UI 元素时自动生成。
渲染模式:
| 模式 |
说明 |
适用场景 |
| Screen Space - Overlay |
UI 覆盖在游戏画面之上(默认) |
主菜单、HUD |
| Screen Space - Camera |
UI 由指定摄像机渲染 |
需要与 3D 场景交互的 UI |
| World Space |
UI 位于 3D 世界中 |
血条飘字、3D 按钮 |
Canvas Scaler
控制 UI 在不同分辨率下的自适应缩放:
| UI Scale Mode |
说明 |
| Constant Pixel Size |
固定像素大小,分辨率高时 UI 变小 |
| Scale With Screen Size |
按参考分辨率等比缩放(推荐) |
| Constant Physical Size |
固定物理尺寸 |
EventSystem
EventSystem 处理 UI 输入事件(点击、悬停、拖拽),创建 Canvas 时自动生成。
11.2 核心 UI 组件
Text (TextMeshPro)
Unity 推荐使用 TextMeshPro(TMP),渲染效果更好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| using TMPro;
public class UIDemo : MonoBehaviour { [SerializeField] private TMP_Text scoreText; [SerializeField] private TMP_Text nameInput;
void Start() { scoreText.text = "Score: 0"; scoreText.text = $"Score: {score}"; scoreText.fontSize = 36; scoreText.color = Color.yellow; scoreText.alignment = TextAlignmentOptions.Center; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| [SerializeField] private Button startButton;
void Start() { startButton.onClick.AddListener(OnStartClicked); startButton.onClick.AddListener(() => { Debug.Log("按钮被点击!"); }); startButton.interactable = false; }
void OnStartClicked() { SceneManager.LoadScene("GameScene"); }
|
Image
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| [SerializeField] private Image healthBar; [SerializeField] private Image icon;
void UpdateHealth(float percent) { healthBar.fillAmount = percent; }
void SetIcon(Sprite sprite) { icon.sprite = sprite; icon.color = Color.white; }
|
11.3 UI 布局组件
| 组件 |
说明 |
| Rect Transform |
UI 元素的变换组件(锚点、轴心、偏移) |
| Vertical/Horizontal Layout Group |
自动垂直/水平排列子元素 |
| Grid Layout Group |
网格排列子元素 |
| Content Size Fitter |
根据内容自动调整大小 |
| Aspect Ratio Fitter |
保持宽高比 |
锚点(Anchor)
锚点决定 UI 元素相对于父级的位置映射:
- 四个角固定:对齐父级角落
- 居中:相对于父级中心
- 拉伸:随父级大小变化自动拉伸
按住 Shift 点击 Anchor Preset 可同时设置锚点和 pivot。
11.4 事件交互
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| using UnityEngine.EventSystems;
public class DragHandler : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IDragHandler { public void OnPointerEnter(PointerEventData eventData) { GetComponent<Image>().color = Color.yellow; }
public void OnPointerExit(PointerEventData eventData) { GetComponent<Image>().color = Color.white; }
public void OnDrag(PointerEventData eventData) { transform.position = eventData.position; } }
|
11.5 实战:简易血条 HUD
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class HealthBar : MonoBehaviour { [SerializeField] private Image healthFill; [SerializeField] private TMP_Text healthText; [SerializeField] private float maxHealth = 100f; private float currentHealth;
void Start() { currentHealth = maxHealth; UpdateUI(); }
public void TakeDamage(float damage) { currentHealth = Mathf.Max(0, currentHealth - damage); UpdateUI(); }
private void UpdateUI() { healthFill.fillAmount = currentHealth / maxHealth; healthText.text = $"{currentHealth}/{maxHealth}"; } }
|
11.6 本章小结
- Canvas 是所有 UI 的容器,三种渲染模式对应不同场景
- Canvas Scaler 控制 UI 自适应
- TextMeshPro 提供高质量文本渲染
- Button 通过
onClick.AddListener 响应点击
- 锚点和布局组件实现 UI 自动适配
- 事件接口(IPointerEnter、IDrag 等)实现交互效果
练习题
- 制作一个包含开始按钮和标题文本的主菜单 UI
- 实现一个血条(Image Fill 模式),绑定到角色生命值
- 使用 Layout Group 制作一个物品栏网格
- 实现按钮悬停变色效果(不使用 Event Trigger,用接口实现)