godot-ui-control

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Godot UI / Control nodes (4.x)

Godot UI / Control nodes (4.x)

Lay out responsive UI with
Control
anchors and
Container
nodes, style it with a
Theme
, and make it navigable by keyboard and gamepad. Targets Godot 4.3+.
使用
Control
锚点和
Container
节点布局响应式UI,通过
Theme
设置样式,并使其支持键盘和游戏手柄导航。适用于**Godot 4.3+**版本。

When to use

适用场景

  • Use when building HUDs, menus, inventories, dialog boxes, or settings screens with
    Control
    -derived nodes; arranging UI that adapts to window size; theming; or wiring focus navigation for controller/keyboard.
When not to use: in-world 2D nodes (
Node2D
/sprites) →
godot-nodes-scenes
; animating UI transitions →
godot-animation
(Tween); genre UIs like card hands →
card-game
/
visual-novel
. For full input rebinding →
input-systems
.
  • 适用于使用
    Control
    派生节点构建HUD、菜单、背包、对话框或设置界面;布局可适配窗口大小的UI;设置主题;或为控制器/键盘配置焦点导航时。
不适用场景: 场景内2D节点(
Node2D
/精灵)→ 参考
godot-nodes-scenes
;UI过渡动画 → 参考
godot-animation
(Tween);卡牌手牌等特定类型UI → 参考
card-game
/
visual-novel
;完整输入重绑定 → 参考
input-systems

Core workflow

核心工作流程

  1. Use
    Control
    nodes for UI
    , not
    Node2D
    . Controls have a rect (position + size), anchors, and participate in focus/theming.
  2. Anchor for responsiveness. Anchors are fractions (0–1) of the parent rect that the Control's edges stick to. Use the editor's Layout presets (Top-Left, Full Rect, Center, etc.) instead of hand-placing pixels.
  3. Let Containers position children. Put children in a
    VBoxContainer
    ,
    HBoxContainer
    ,
    GridContainer
    ,
    MarginContainer
    , etc. — the container sets their position/size; you control flow with
    size_flags
    . Don't set child anchors inside a container (it overrides them).
  4. Style with a
    Theme
    .
    Assign a
    Theme
    resource on a top Control; children inherit it. Override per-node with theme overrides only when necessary.
  5. Wire focus so gamepad/keyboard can move between buttons; set a default focused control and define neighbors or rely on auto-neighbor.
  6. Connect signals (
    pressed
    ,
    toggled
    ,
    text_submitted
    ,
    value_changed
    ).
  1. 使用
    Control
    节点构建UI
    ,而非
    Node2D
    。Control节点包含矩形(位置+尺寸)、锚点,并支持焦点和主题功能。
  2. 利用锚点实现响应式布局。锚点是父节点矩形的比例值(0–1),Control节点的边缘会贴合锚点位置。使用编辑器的布局预设(左上、全屏、居中等),而非手动设置像素位置。
  3. 让Container节点自动定位子节点。将子节点放入
    VBoxContainer
    HBoxContainer
    GridContainer
    MarginContainer
    等容器中——容器会设置子节点的位置/尺寸;你可以通过
    size_flags
    控制布局流。不要在容器内设置子节点的锚点(这会被容器覆盖)。
  4. 使用
    Theme
    设置样式
    。在顶层Control节点上分配
    Theme
    资源;子节点会继承该主题。仅在必要时通过主题覆写为单个节点设置样式。
  5. 配置焦点,使游戏手柄/键盘可在按钮间切换;设置默认聚焦的Control节点,定义相邻焦点或依赖自动相邻功能。
  6. 连接信号
    pressed
    toggled
    text_submitted
    value_changed
    )。

Patterns

模式示例

1. Responsive layout with anchors (code form)

1. 锚点实现响应式布局(代码形式)

gdscript
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
gdscript
extends Control

func _ready() -> void:
    # 让此面板拉伸填充父节点(等同于“全屏”预设)。
    anchors_preset = Control.PRESET_FULL_RECT
    # 或者手动设置锚点:四个边缘均贴合父节点的角落。
    # anchor_left = 0; anchor_top = 0; anchor_right = 1; anchor_bottom = 1

2. A menu built from containers + button signals

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

gdscript
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()
gdscript
extends VBoxContainer    # 子节点垂直堆叠,自动调整尺寸

func _ready() -> void:
    for child in get_children():
        if child is Button:
            child.pressed.connect(_on_button_pressed.bind(child.name))
    # 让第一个按钮获得焦点,以便游戏手柄可立即导航。
    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: make one child expand to fill leftover space

3. 尺寸标志:让单个子节点填充剩余空间

gdscript
undefined
gdscript
undefined

In a HBoxContainer: a label on the left, a spacer that eats remaining width.

在HBoxContainer中:左侧是标签,右侧是占据剩余宽度的间隔器。

func _ready() -> void: $Label.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN $Spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL # grows to fill
undefined
func _ready() -> void: $Label.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN $Spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL # 自动扩展填充
undefined

4. Theme override for one node (without a full Theme resource)

4. 单个节点的主题覆写(无需完整Theme资源)

gdscript
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"))
gdscript
func _ready() -> void:
    # 单个节点覆写:使用add_theme_*(特定类型的设置器)。
    $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"))

Pitfalls

常见陷阱

  • Mixing manual position with Containers. A child of a
    Container
    cannot set its own position/anchors — the container owns layout. To free-place, take the node out of the container or use a plain
    Control
    /
    PanelContainer
    wrapper.
  • Anchors vs offsets. Anchors are fractions of the parent; offsets are pixel deltas from the anchored point. Set anchors via presets, then nudge with offsets. Setting only position while anchors are at 0 makes UI not scale with the window.
  • Node2D
    for UI.
    Buttons/labels parented under a
    Node2D
    won't theme or take focus correctly. Keep UI under a
    CanvasLayer
    /
    Control
    subtree.
  • Focus lost on gamepad. If nothing is focused, directional input does nothing. Call
    grab_focus()
    on an initial control and ensure
    focus_mode
    is not
    FOCUS_NONE
    .
  • Theme vs theme override. A
    Theme
    resource styles a whole subtree;
    add_theme_*
    overrides one node. Overusing per-node overrides defeats centralized theming.
  • rect_*
    properties are renamed.
    Godot 3's
    rect_size
    /
    rect_position
    /
    rect_min_size
    are now
    size
    /
    position
    /
    custom_minimum_size
    in 4.x.
  • mouse_filter
    on a full-rect Control can swallow clicks meant for nodes beneath it; set
    MOUSE_FILTER_IGNORE
    on purely decorative panels.
  • 手动位置与Container混用
    Container
    的子节点无法自行设置位置/锚点——容器拥有布局控制权。如需自由放置,将节点移出容器,或使用普通
    Control
    /
    PanelContainer
    作为包装器。
  • 锚点与偏移混淆。锚点是父节点的比例值;偏移是锚点位置的像素增量。通过预设设置锚点,然后用偏移微调。仅设置位置而锚点为0时,UI将无法随窗口缩放。
  • 使用
    Node2D
    构建UI
    。父节点为
    Node2D
    的按钮/标签无法正确应用主题或获取焦点。应将UI置于
    CanvasLayer
    /
    Control
    子树之下。
  • 游戏手柄焦点丢失。若没有任何节点获得焦点,方向输入将无效。在初始Control节点上调用
    grab_focus()
    ,并确保
    focus_mode
    未设置为
    FOCUS_NONE
  • 主题与主题覆写混淆
    Theme
    资源为整个子树设置样式;
    add_theme_*
    仅覆写单个节点。过度使用单个节点覆写会破坏集中式主题管理。
  • rect_*
    属性重命名
    。Godot 3中的
    rect_size
    /
    rect_position
    /
    rect_min_size
    在4.x版本中已更名为
    size
    /
    position
    /
    custom_minimum_size
  • **全屏Control节点的
    mouse_filter
    **可能会遮挡下方节点的点击操作;对于纯装饰性面板,应设置为
    MOUSE_FILTER_IGNORE

References

参考资料

  • For the anchor/offset math, every Container type, building/extending Theme and StyleBox resources, focus neighbor wiring, and
    CanvasLayer
    for HUDs, read
    references/layout-and-theming.md
    .
  • 关于锚点/偏移的计算逻辑、每种Container类型的用法、Theme和StyleBox资源的创建/扩展、焦点相邻配置,以及用于HUD的
    CanvasLayer
    ,请阅读
    references/layout-and-theming.md

Related skills

相关技能

  • game-ui-ux
    — cross-engine UI/UX: responsive scaling, safe areas, focus navigation, screen flow.
  • godot-animation
    — Tween-based UI transitions and juicing.
  • godot-signals-groups
    — connecting UI events to game logic.
  • input-systems
    — rebindable input and multi-device focus.
  • card-game
    /
    visual-novel
    — UI-heavy genre templates.
  • game-ui-ux
    —— 跨引擎UI/UX:响应式缩放、安全区域、焦点导航、屏幕流程。
  • godot-animation
    —— 基于Tween的UI过渡与动效优化。
  • godot-signals-groups
    —— 将UI事件连接至游戏逻辑。
  • input-systems
    —— 可重绑定输入与多设备焦点。
  • card-game
    /
    visual-novel
    —— 重度UI的类型模板。