10. 游戏 UI 界面
2026/4/13大约 3 分钟
游戏 UI 界面
UI(用户界面)是游戏的骨架——主菜单、血条、分数、设置菜单,都属于 UI。
建议在实现核心功能(移动、战斗)之前就把 UI 框架搭好,这样后续开发时可以直接在完整框架上添加功能。
一个完整游戏需要哪些界面
[主菜单] → [关卡选择] → [游戏进行中] → [胜利/失败] → [回到主菜单]主菜单场景
主菜单是玩家启动游戏后看到的第一个画面:
MainMenu (Control) ← UI 根节点
├── TextureRect ← 背景图片
├── VBoxContainer ← 垂直排列容器
│ ├── Label "游戏标题" ← 标题文字
│ ├── Button "开始游戏"
│ ├── Button "设置"
│ └── Button "退出"
└── AudioStreamPlayer ← 背景音乐C
using Godot;
// 主菜单按钮逻辑
public partial class MainMenu : Control
{
private void OnStartPressed()
{
GetTree().ChangeSceneToFile("res://levels/level_01/level_01.tscn");
}
private void OnSettingsPressed()
{
GetNode<Control>("SettingsPanel").Show();
}
private void OnQuitPressed()
{
GetTree().Quit();
}
}GDScript
# 主菜单按钮逻辑
extends Control
func _on_start_pressed():
get_tree().change_scene_to_file("res://levels/level_01/level_01.tscn")
func _on_settings_pressed():
$SettingsPanel.show()
func _on_quit_pressed():
get_tree().quit()HUD(游戏进行中的信息显示)
HUD(Heads Up Display)是叠加在游戏画面上的信息面板,显示分数、血量、时间等:
HUD (CanvasLayer) ← CanvasLayer 让 UI 始终在最上层
├── MarginContainer ← 边距容器
│ ├── HBoxContainer ← 水平排列
│ │ ├── Label "分数: 0"
│ │ └── TextureProgressBar ← 血条
│ └── Label "时间: 60"
└── VBoxContainer
└── Label "提示信息"为什么用 CanvasLayer
CanvasLayer 会让它里面的所有 UI 元素始终显示在画面最上层,不会被游戏中的角色或地图遮挡。就像把一张透明贴纸贴在屏幕上一样。
HUD 通常作为独立场景,然后在游戏主场景中实例化:
C
using Godot;
// 在游戏主场景中加载 HUD
public override void _Ready()
{
var hudScene = GD.Load<PackedScene>("res://hud/hud.tscn");
var hud = hudScene.Instantiate<Node>();
AddChild(hud);
}GDScript
# 在游戏主场景中加载 HUD
func _ready():
var hud = preload("res://hud/hud.tscn").instantiate()
add_child(hud)游戏结束画面
C
using Godot;
// 游戏结束逻辑
public partial class GameOverScreen : Control
{
public void ShowGameOver(int score)
{
GetNode<Label>("ScoreLabel").Text = "最终得分: " + score.ToString();
GetNode<Control>("GameOverPanel").Show();
GetTree().Paused = true; // 暂停游戏
}
private void OnRetryPressed()
{
GetTree().Paused = false;
GetTree().ReloadCurrentScene(); // 重新加载当前关卡
}
private void OnMenuPressed()
{
GetTree().Paused = false;
GetTree().ChangeSceneToFile("res://main_menu/main_menu.tscn");
}
}GDScript
# 游戏结束逻辑
extends Control
func show_game_over(score: int):
$ScoreLabel.text = "最终得分: " + str(score)
$GameOverPanel.show()
get_tree().paused = true # 暂停游戏
func _on_retry_pressed():
get_tree().paused = false
get_tree().reload_current_scene() # 重新加载当前关卡
func _on_menu_pressed():
get_tree().paused = false
get_tree().change_scene_to_file("res://main_menu/main_menu.tscn")设置界面
设置界面通常包含:
音量调节
C
using Godot;
// 音量控制
private void OnMasterVolumeChanged(double value)
{
// 滑块值(0~1)转为分贝
double db = Mathf.LinearToDb(value);
AudioServer.SetBusVolumeDb(0, db); // 0 号总线是主音量
}GDScript
# 音量控制
func _on_master_volume_changed(value):
# 滑块值(0~1)转为分贝
var db = linear_to_db(value)
AudioServer.set_bus_volume_db(0, db) # 0 号总线是主音量全屏切换
C
using Godot;
private void OnFullscreenToggled(bool buttonPressed)
{
if (buttonPressed)
{
DisplayServer.WindowSetMode(DisplayServer.WindowMode.Fullscreen);
}
else
{
DisplayServer.WindowSetMode(DisplayServer.WindowMode.Windowed);
}
}GDScript
func _on_fullscreen_toggled(button_pressed):
if button_pressed:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
else:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)场景切换技巧
带淡入淡出效果的场景切换,让过渡更自然:
C
using Godot;
// 带淡入淡出的场景切换
public async void ChangeScene(string target)
{
var tween = CreateTween();
// 淡出到黑色
tween.TweenProperty(GetNode<ColorRect>("FadeOverlay"), "color:a", 1.0, 0.5);
await ToSignal(tween, Tween.SignalName.Finished);
// 切换场景
GetTree().ChangeSceneToFile(target);
// 淡入
tween.TweenProperty(GetNode<ColorRect>("FadeOverlay"), "color:a", 0.0, 0.5);
}GDScript
# 带淡入淡出的场景切换
func change_scene(target: String):
var tween = create_tween()
# 淡出到黑色
tween.tween_property($FadeOverlay, "color:a", 1.0, 0.5)
await tween.finished
# 切换场景
get_tree().change_scene_to_file(target)
# 淡入
tween.tween_property($FadeOverlay, "color:a", 0.0, 0.5)常用 UI 容器
| 容器 | 布局方式 | 使用场景 |
|---|---|---|
VBoxContainer | 子元素垂直排列 | 菜单按钮列表 |
HBoxContainer | 子元素水平排列 | 顶部状态栏 |
GridContainer | 子元素按网格排列 | 关卡选择、背包格子 |
MarginContainer | 子元素保持边距 | 整体页面布局 |
CenterContainer | 子元素居中 | 对话框、弹窗 |
下一章
UI 框架搭好了,接下来实现敌人的 AI 行为。
