返回 Skills 目录
gamedev-skills/awesome-gamedev-agent-skills已通过检查

SKILL DETAIL

godot-ui-control

gamedev-skills/awesome-gamedev-agent-skills/godot-ui-control

Build Godot 4.7 user interfaces with Control nodes: anchors and offsets for responsive layout, Container nodes (VBox/HBox/Grid/Margin) for automatic arrangement, Theme resources for consistent styling, and keyboard/gamepad focus navigation. Use when laying out a HUD, menu, or UI in a Godot project, working with Control/Container nodes, anchors, themes, or focus in a .tscn.

安装量 · 302查看来源

Installation

npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill godot-ui-control

技能文件

SKILL.md

最近同步 · 2026年10月22日

references/layout-and-theming.md›
# Control layout & theming reference (Godot 4.7)

Depth companion to `godot-ui-control`.

## Anchors and offsets

A `Control` has four anchors (`anchor_left/top/right/bottom`), each a fraction `0.0–1.0`
of the parent's rect, and four offsets (`offset_left/top/right/bottom`) in pixels from the
anchored point.

- Anchors at `(0,0,0,0)` → the control's edges all track the parent's top-left; size is
  driven entirely by offsets (fixed pixel size, top-left aligned).
- Anchors at `(0,0,1,1)` (Full Rect) → edges track each corner; the control resizes with
  the parent. Offsets become margins.
- Center presets set anchors to `0.5` and use offsets relative to the center.

Use `anchors_preset = Control.PRESET_*` (CENTER, FULL_RECT, TOP_WIDE, BOTTOM_RIGHT, ...)
or the editor's Layout toolbar; it sets anchors and offsets together.

## Container types

| Container | Arranges children |
|-----------|-------------------|
| `VBoxContainer` / `HBoxContainer` | Stacked vertically / horizontally |
| `GridContainer` | Grid with `columns` |
| `MarginContainer` | Adds margins (theme constants `margin_*`) |
| `CenterContainer` | Centers a single child at its min size |
| `PanelContainer` | Draws a panel stylebox behind one child |
| `ScrollContainer` | Scrolls oversized content |
| `TabContainer` | Tabbed pages |
| `AspectRatioContainer` | Keeps child aspect ratio |
| `SplitContainer` (H/V) | Draggable splitter between two children |
| `FlowContainer` (H/V) | Wraps children like text |

Containers ignore child anchors/positions and instead use **size flags**.

## Size flags

```gdscript
size_flags_horizontal / size_flags_vertical:
  SIZE_FILL            # fill assigned space
  SIZE_EXPAND          # claim extra space (combine with FILL: SIZE_EXPAND_FILL)
  SIZE_SHRINK_BEGIN    # shrink to min, align to start
  SIZE_SHRINK_CENTER   # shrink to min, centered
  SIZE_SHRINK_END      # shrink to min, align to end
size_flags_stretch_ratio = 2.0   # relative share of expand space among siblings
```

## Theme and StyleBox

A `Theme` resource maps (control type, property name) → value. Property kinds: `color`,
`constant`, `font`, `font_size`, `icon`, `stylebox`.

```gdscript
var theme := Theme.new()
theme.set_color("font_color", "Button", Color.WHITE)
theme.set_font_size("font_size", "Button", 18)
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.1, 0.1, 0.15)
sb.set_corner_radius_all(8)
sb.set_content_margin_all(12)
theme.set_stylebox("normal", "Button", sb)
control.theme = theme        # inherited by the whole subtree
```

Per-node overrides (win over the inherited Theme):

```gdscript
add_theme_color_override("font_color", Color.RED)
add_theme_font_size_override("font_size", 24)
add_theme_stylebox_override("panel", my_stylebox)
add_theme_constant_override("separation", 16)   # e.g. VBox spacing
remove_theme_color_override("font_color")
```

`StyleBoxFlat` (solid color, borders, corners, shadows), `StyleBoxTexture` (9-patch
texture), and `StyleBoxEmpty` cover most needs.

## Focus navigation (keyboard / gamepad)

```gdscript
control.focus_mode = Control.FOCUS_ALL        # FOCUS_NONE | FOCUS_CLICK | FOCUS_ALL
control.grab_focus()
# Explicit neighbors (NodePaths) override automatic geometry-based neighbor finding:
control.focus_neighbor_bottom = next_button.get_path()
control.focus_next = other.get_path()         # Tab order
```

The default UI input actions (`ui_up/down/left/right/accept/cancel/focus_next`) drive
focus movement; they map to arrow keys, Enter, and the gamepad D-pad/face buttons out of
the box.

## HUDs over the game

Put HUD UI under a `CanvasLayer` so it renders on top of and independent from the moving
game camera. A `Control` set to Full Rect inside the CanvasLayer fills the viewport
regardless of world scrolling.

## Common signals

- `Button.pressed`, `Button.toggled(toggled_on)`, `Button.button_down/up`.
- `LineEdit.text_submitted(text)`, `text_changed(text)`.
- `Slider/SpinBox.value_changed(value)`.
- `ItemList.item_selected(index)`, `OptionButton.item_selected(index)`.
- `Control.gui_input(event)` for custom click/drag handling.
SKILL.md›
---
name: godot-ui-control
description: >
  Build Godot 4.7 user interfaces with Control nodes: anchors and offsets for
  responsive layout, Container nodes (VBox/HBox/Grid/Margin) for automatic
  arrangement, Theme resources for consistent styling, and keyboard/gamepad focus
  navigation. Use when laying out a HUD, menu, or UI in a Godot project, working
  with Control/Container nodes, anchors, themes, or focus in a .tscn.
---

# 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.7**.

## 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`.

## 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`).

## Patterns

### 1. Responsive layout with anchors (code form)

```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
```

### 2. A menu built from containers + button signals

```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()
```

### 3. Size flags: make one child expand to fill leftover space

```gdscript
# 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 override for one node (without a full Theme resource)

```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"))
```

## 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.

## 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`.

## 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.