mcpField
G
godot-ui

godot-ui

github.com/jame581设计与 UI901200 次安装1 周前更新
代码仓库

关于 godot-ui

面向 Godot 4.3+ 的 UI 技能,涵盖 Control 节点、布局、主题、焦点与常见界面模式,为使用 GDScript 或 C# 构建游戏界面的开发者提供指导。

主要功能

  1. 01Control 层级与布局
  2. 02Container 和锚点指南
  3. 03Theme 与 StyleBox 设置
  4. 04键盘和手柄焦点导航
  5. 05菜单、设置和暂停界面模式
  6. 06信号与可折叠 UI 元素

适用场景

  1. 01构建主菜单或设置界面
  2. 02安排 HUD 或对话框面板
  3. 03支持键盘和手柄导航
  4. 04制作可折叠面板和多层标签效果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jame581/godotprompter --skill godot-ui

安装后在 Claude Code 中输入/godot-ui确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
anchors-in-code.md
focus-and-navigation.md
foldable-container.md
signals.md
theme-system.md
ui-patterns.md

详细介绍

Godot UI——Control 节点、主题与布局

所有示例均面向 Godot 4.3+,不使用已弃用的 API;优先使用 GDScript,其次是 C#。

相关技能: 多分辨率缩放请参阅 responsive-ui,游戏内 HUD 模式请参阅 hud-system,对话 UI 展示请参阅 dialogue-system,UI 过渡与动画效果请参阅 tween-animation。


1. Control 节点层级

Control 与 Node2D 的区别

Control 是所有 UI 节点的基类——它位于与 Node2D/Node3D 不同的场景树分支中,采用完全不同的布局模型。

特性Node2DControl
位置模型世界空间中的 position(相对于父节点的像素坐标)相对于父节点矩形的锚点和偏移量
大小无固有大小具有 size、custom_minimum_size 和计算得出的最小尺寸(get_combined_minimum_size())
主题无继承并覆盖 Theme 资源
焦点不适用内置焦点系统(focus_mode、grab_focus())
鼠标事件通过 _input 手动处理gui_input、mouse_entered、mouse_exited
布局辅助项无Container 子类会自动排列子节点
Control 作为基类

每个 UI 控件(Button、Label、LineEdit 等)都继承自 Control。Control 本身定义的关键属性包括:

  • anchor_left、anchor_top、anchor_right、anchor_bottom——相对于父节点矩形的比例值(0.0–1.0)
  • offset_left、offset_top、offset_right、offset_bottom——锚点解析后应用的像素偏移量
  • size_flags_horizontal、size_flags_vertical——节点参与 Container 布局的方式
  • theme——Theme 资源;查找时会从最近的祖先 Control/Window 开始,逐级检查拥有主题的节点,并在遇到第一个既不是 Control 也不是 Window 的父节点时停止(例如 CanvasLayer 或 Node2D)
  • focus_mode——节点是否可以接收键盘/游戏手柄焦点

将 UI 节点放在 CanvasLayer 中,使其渲染在 3D/2D 世界上方,并且不受 Camera2D 变换影响。场景根节点内置画布(第 0 层)上的控件会随 Camera2D 移动,因为摄像机会设置该画布的变换。

⚠️ Godot 4.7 中的变更: Control.accessibility_live 的类型从 DisplayServer.AccessibilityLiveMode 变为 AccessibilityServer.AccessibilityLiveMode(默认值为 LIVE_OFF = 0,另有 LIVE_POLITE、LIVE_ASSERTIVE)——无障碍枚举/API 已移至新的 AccessibilityServer 单例。与 GDScript 兼容;会破坏 C# 二进制/源代码兼容性(需针对新枚举重新构建)。请参阅 4.7 迁移指南。


2. 常见容器节点

容器用途适用场景
VBoxContainer垂直排列子节点列表、选项行、垂直菜单
HBoxContainer水平排列子节点工具栏、状态行、水平导航
GridContainer将子节点排列成固定列数的网格物品栏网格、按键绑定表
MarginContainer为单个子节点添加边距包装任意节点,为其留出空间
PanelContainer绘制 StyleBox 背景,然后排列子节点卡片 UI、对话框、HUD 面板
ScrollContainer使其单个子节点可滚动;裁剪溢出内容长列表、日志、可滚动设置界面
TabContainer将子节点排列为带名称的选项卡;一次显示一个设置界面、多分区面板

尺寸设置提示:

  • 对需要填满可用空间的子节点,将 size_flags_horizontal = SIZE_EXPAND_FILL。
  • 使用 custom_minimum_size 防止子节点收缩到零。
  • MarginContainer 从主题属性 margin_* 读取边距;可在运行时通过 add_theme_constant_override("margin_left", 16) 覆盖。

Godot 4.7+:custom_maximum_size(Vector2(-1, -1))按轴限制尺寸,其优先级高于 custom_minimum_size;propagate_maximum_size(默认值为 false)使父节点的最大尺寸约束其 Control 子节点;_get_maximum_size() 可从代码计算最大尺寸。

⚠️ Godot 4.7 中的变更:TabContainer.all_tabs_in_front 已弃用——现在不再起作用,因为选项卡始终位于前景。请移除设置该属性的代码。参见 GH-118623。


3. 锚点与边距

锚点预设的工作原理

锚点是父级矩形上的一个点,以分数表示(0 = 上边缘/左边缘,1 = 下边缘/右边缘)。Godot 按以下方式计算每条边的最终像素位置:

final_left   = parent_width  * anchor_left   + offset_left
final_top    = parent_height * anchor_top    + offset_top
final_right  = parent_width  * anchor_right  + offset_right
final_bottom = parent_height * anchor_bottom + offset_bottom

编辑器提供了内置预设:

预设锚点值用途
完整矩形L=0, T=0, R=1, B=1覆盖/填充父级——根 UI 最常用
居中L=0.5, T=0.5, R=0.5, B=0.5在父级中居中的固定尺寸组件
左上L=0, T=0, R=0, B=0固定尺寸组件,固定在左上角
右上L=1, T=0, R=1, B=0固定尺寸组件,固定在右上角
底部居中L=0.5, T=1, R=0.5, B=1锚定在底部中央的 HUD 元素
在代码中设置锚点

每条边的锚点都按 parent_size * anchor + offset 计算,因此手动设置时需要设置 8 个属性。set_anchors_and_offsets_preset(Control.PRESET_*) 可以通过一次调用完成这些设置——使用该方法,然后调整 offset_* 设置边距(右侧/底部使用负值)。

锚点与偏移量的规则(将偏移量保持为 0,让锚点负责定位),以及完整的 GDScript + C# 示例——完整矩形填充、带 16 px 边距的右上 HUD、自定义半屏侧边面板:references/anchors-in-code.md


4. 主题系统

Theme 资源集中管理字体、颜色和 StyleBox。在根节点应用主题,让继承机制处理其余部分;仅在需要单独调整时使用 theme_override_*。StyleBoxFlat 可满足大多数扁平化设计需求(bg_color、border_color、corner_radius_*、border_width_*);纹理则使用 StyleBoxTexture。

完整的 Theme 资源创建指南、StyleBoxFlat 属性、字体覆盖、主题继承规则,以及各节点的 theme_override_* 方法,请参见 references/theme-system.md。

Godot 4.7+:GradientTexture2D 的 Fill 枚举新增 FILL_CONIC——颜色按圆锥(角度)模式插值;无需着色器即可制作径向进度/冷却指示器(C#:FillEnum.Conic)。


5. 焦点与导航

焦点模式(FOCUS_NONE、FOCUS_CLICK、FOCUS_ALL)控制键盘/游戏手柄导航。使用 focus_neighbor_top / _bottom / _left / _right 配置焦点链,或依靠自动空间检测。菜单打开时,对第一个可交互元素调用 grab_focus()。

焦点模式详情、focus_neighbor 焦点链示例、游戏手柄/键盘输入处理,以及 grab_focus 用法,请参阅 references/focus-and-navigation.md。


6. 常见 UI 模式

三种典型场景:主菜单(居中的 VBoxContainer,包含标题和按钮列表)、带标签页的设置界面(TabContainer,每个类别对应一个子面板),以及暂停菜单覆盖层(全矩形 ColorRect 背景加居中的选项面板,通过 get_tree().paused = true 暂停)。

每种模式的完整场景树片段和 GDScript 配置,请参阅 references/ui-patterns.md。

Godot 4.7+: offset_transform_* — 仅影响视觉效果的 UI 动效变换(抖动/脉冲),不会重新触发容器布局;_get_cursor_shape(at_position) — 按位置设置光标形状;PopupMenu 搜索栏(search_bar_enabled,默认使用模糊搜索)以及用于重新排序的 set_item_index();TextureRect 的 STRETCH_TILE 现在支持平铺 AtlasTexture(仅不支持非零 margin)。代码见:references/ui-patterns.md。

⚠️ Godot 4.7 中的变更: RichTextLabel.add_image() / update_image() 的尺寸设置已重做 — width / height 现在是 float;width_in_percent / height_in_percent 布尔值改为 width_unit / height_unit,并使用新的 ImageUnit 枚举(IMAGE_UNIT_PIXEL、IMAGE_UNIT_PERCENT、IMAGE_UNIT_EM — em 随字体大小缩放)。ImageUpdateMask.UPDATE_WIDTH_IN_PERCENT 已重命名为 UPDATE_WIDTH_UNIT,使用旧名称的 GDScript 将无法运行。请参阅 4.7 迁移指南。


7. 信号

点击使用 Button.pressed,节点上的原始事件使用 Control.gui_input,悬停使用 Control.mouse_entered / mouse_exited。在 _ready() 中连接,或通过检查器的 Node 面板连接。

完整的信号目录和信号驱动的 UI 更新模式,请参阅 references/signals.md。


8. FoldableContainer(Godot 4.5+)

FoldableContainer 是 Godot 4.5 新增的内置手风琴式 Container — 包含一个切换标题和可折叠的子项,可取代以往将 Button 连接到显示/隐藏 VBoxContainer 的繁琐写法。设置 title,设置 folded 作为初始状态,照常添加子项,并监听 folding_changed(is_folded)。

完整的 GDScript + C# 构建示例、关键属性表和切换信号:references/foldable-container.md


9. 叠加式标签效果(Godot 4.5+)

Godot 4.5 允许 Label 通过其 LabelSettings 资源叠加多个轮廓和阴影 — 例如,使用不同宽度/颜色的两个轮廓,再加上柔和的投影。叠加效果配置在 LabelSettings 上(按索引设置),而非主题覆盖中;RichTextLabel 没有对应功能。此前,要叠加多个轮廓,必须复制并手动分层放置 Label 节点。

# Stacked effects live on LabelSettings and are configured per index.
func apply_stacked_outlines(label: Label) -> void:
    var settings := LabelSettings.new()
    settings.outline_size = 4                  # base (inner) outline
    settings.outline_color = Color.BLACK

    settings.add_stacked_outline()             # stacked outline 0, drawn outside the base one
    settings.set_stacked_outline_size(0, 8)
    settings.set_stacked_outline_color(0, Color.GOLD)

    settings.add_stacked_shadow()              # stacked shadow 0
    settings.set_stacked_shadow_offset(0, Vector2(3, 3))
    settings.set_stacked_shadow_color(0, Color(0.0, 0.0, 0.0, 0.5))
    settings.set_stacked_shadow_outline_size(0, 2)

    label.label_settings = settings            # takes priority over theme properties
public void ApplyStackedOutlines(Label label)
{
    var settings = new LabelSettings { OutlineSize = 4, OutlineColor = Colors.Black };

    settings.AddStackedOutline();
    settings.SetStackedOutlineSize(0, 8);
    settings.SetStackedOutlineColor(0, Colors.Gold);

    settings.AddStackedShadow();
    settings.SetStackedShadowOffset(0, new Vector2(3, 3));
    settings.SetStackedShadowColor(0, new Color(0f, 0f, 0f, 0.5f));
    settings.SetStackedShadowOutlineSize(0, 2);

    label.LabelSettings = settings;
}

RichTextLabel 无法叠加效果;它通过 BBCode 为每段文本设置一个轮廓:[outline_size=4][outline_color=#000000]Level Up![/outline_color][/outline_size]。

编辑器工作流: 在 Label 的 Label Settings 属性中创建 LabelSettings 资源,并在其叠加轮廓和叠加阴影列表中添加条目。上面的按索引调用适用于动态场景。


10. 检查清单

  • 根 UI Control 的锚点预设为 Full Rect(或适合布局的预设)
  • 所有交互式控件(Button、LineEdit、Slider)均设置了 focus_mode = FOCUS_ALL
  • 装饰性节点(Label、TextureRect)均设置了 focus_mode = FOCUS_NONE
  • 为非线性布局设置焦点邻居,确保手柄导航能够正确循环
  • 每个屏幕都在 _ready() 中对第一个交互式控件调用 grab_focus()
  • 暂停菜单的根 Control 设置了 process_mode = PROCESS_MODE_ALWAYS
  • 在屏幕根节点上指定一个 Theme 资源,而不是在每个子节点上重复指定
  • 简单的纯色面板使用 StyleBoxFlat,而非图像资源
  • 单个节点的覆盖项使用 add_theme_*_override(),而非指定一个全新的 Theme
  • 使用容器(VBoxContainer、HBoxContainer 等)进行布局,而非手动设置 position 值
  • 为不得缩小为零的控件设置 custom_minimum_size
  • 滑块和音量代码使用 linear_to_db / db_to_linear,而非将原始线性值映射到音频总线
  • 在 _ready() 中(或通过编辑器)连接信号;不要在 _process 中轮询 UI 状态
  • TabContainer 中的标签页顺序与逻辑阅读/导航顺序一致
  • 手风琴式可折叠面板使用 FoldableContainer,而非手动连接 Button 和 VBoxContainer(Godot 4.5+)
  • Label 上的多层轮廓/阴影使用 LabelSettings 堆叠轮廓/阴影,而非重复创建节点(Godot 4.5+)

评论

支持 Markdown