返回技能市场
开发运维 安全

godot-ui-control

@admin/godot-ui-control

用 Godot 的 Control 与容器节点制作 HUD 和菜单,设置响应式布局、主题及键盘和手柄焦点。

admin 热度 446v0.0.1

Godot UI / Control 节点(4.x)

使用 Control 锚点和 Container 节点布置响应式 UI,使用 Theme 设置样式,并使其可通过键盘和手柄导航。目标版本为 Godot 4.7

何时使用

  • 使用 Control 派生节点构建 HUD、菜单、物品栏、对话框或设置界面;布置适配窗口大小的 UI;设置主题;或为手柄/键盘连接焦点导航时使用。

何时不要使用: 世界内 2D 节点(Node2D/精灵)→ godot-nodes-scenes;动画化 UI 过渡 → godot-animation(Tween);卡牌手牌等类型 UI → card-game/visual-novel。完整输入重绑定 → input-systems

核心工作流

  1. UI 使用 Control 节点,而不是 Node2D。Control 具有矩形(位置 + 尺寸)、锚点,并参与焦点/主题设置。
  2. 使用锚点实现响应式。 锚点是 Control 边缘吸附到的父节点矩形的比例(0–1)。使用编辑器的 Layout 预设(Top-Left、Full Rect、Center 等),而不是手动放置像素。
  3. 让 Container 定位子节点。 将子节点放入 VBoxContainerHBoxContainerGridContainerMarginContainer 等容器 — 容器设置它们的位置/尺寸;你通过 size_flags 控制流。不要在容器内设置子节点锚点(这会覆盖它们)。
  4. 使用 Theme 设置样式。 在顶层 Control 上分配一个 Theme 资源;子节点会继承它。仅在必要时使用主题覆盖覆盖单个节点。
  5. 连接焦点,使手柄/键盘可以在按钮之间移动;设置默认聚焦控件,并定义邻居或依赖自动邻居。
  6. 连接信号pressedtoggledtext_submittedvalue_changed)。

模式

1. 使用锚点进行响应式布局(代码形式)

extends Control

func _ready() -> void:
    # Stretch this panel to fill its parent (equivalent to the "Full Rect" preset).
    anchors_preset = Control.PRESET_FULL_RECT
    # Or set anchors manually: all four edges at the parent's far corners.
    # anchor_left = 0; anchor_top = 0; anchor_right = 1; anchor_bottom = 1

2. 由容器 + 按钮信号构建的菜单

extends VBoxContainer    # children stack vertically, auto-sized

func _ready() -> void:
    for child in get_children():
        if child is Button:
            child.pressed.connect(_on_button_pressed.bind(child.name))
    # Give the first button focus so a gamepad can navigate immediately.
    if get_child_count() > 0:
        (get_child(0) as Control).grab_focus()

func _on_button_pressed(which: StringName) -> void:
    match which:
        "PlayButton":  get_tree().change_scene_to_file("res://game.tscn")
        "QuitButton":  get_tree().quit()

3. size_flags:让一个子节点扩展以填充剩余空间

# In a HBoxContainer: a label on the left, a spacer that eats remaining width.
func _ready() -> void:
    $Label.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
    $Spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL   # grows to fill

4. 单个节点的 Theme 覆盖(不使用完整 Theme 资源)

func _ready() -> void:
    # Per-node overrides: use add_theme_* (type-specific setters).
    $Title.add_theme_font_size_override("font_size", 32)
    $Title.add_theme_color_override("font_color", Color.GOLD)
    $Panel.add_theme_stylebox_override("panel", preload("res://ui/panel.stylebox.tres"))

常见陷阱

  • 在 Container 中混用手动位置。 Container 的子节点不能设置自己的位置/锚点 — 容器拥有布局。要自由放置,请将节点移出容器,或使用普通 Control/PanelContainer 包装器。
  • 锚点与偏移。 锚点是父节点矩形的比例;偏移是相对于锚定点的像素增量。通过预设设置锚点,然后使用偏移微调。如果锚点保持为 0,只设置位置会导致 UI 不随窗口缩放。
  • 使用 Node2D 处理 UI。 父节点为 Node2D 的按钮/标签不会正确应用主题或获取焦点。将 UI 放在 CanvasLayer/Control 子树下。
  • 手柄失去焦点。 如果没有控件获得焦点,方向输入不会起作用。在初始控件上调用 grab_focus(),并确保 focus_mode 不是 FOCUS_NONE
  • Theme 与主题覆盖。 Theme 资源为整个子树设置样式;add_theme_* 覆盖单个节点。过度使用单节点覆盖会破坏集中式主题管理。
  • **rect_* 属性已重命名。** Godot 3 的 rect_size/rect_position/rect_min_size 在 4.x 中现在是 size/position/custom_minimum_size
  • mouse_filter 在全矩形 Control 上可能会吞掉本应发给其下方节点的点击;在纯装饰性面板上设置 MOUSE_FILTER_IGNORE

参考资料

  • 有关锚点/偏移计算、每种 Container 类型、构建/扩展 Theme 和 StyleBox 资源、焦点邻居连接,以及用于 HUD 的 CanvasLayer,请阅读 references/layout-and-theming.md

相关技能

  • game-ui-ux — 跨引擎 UI/UX:响应式缩放、安全区域、焦点导航、屏幕流程。
  • godot-animation — 基于 Tween 的 UI 过渡与效果增强。
  • godot-signals-groups — 将 UI 事件连接到游戏逻辑。
  • input-systems — 可重绑定输入和多设备焦点。
  • card-game / visual-novel — 以 UI 为主的游戏类型模板。
qianwen skills install @admin/godot-ui-control