关于 game-ui-ux
game-ui-ux 是一项与引擎无关的技能,用于设计适配不同屏幕尺寸和输入设备的游戏 HUD、菜单与覆盖层。重点包括响应式布局、焦点导航、屏幕栈和事件驱动的 UI 更新。
主要功能
- 01响应式锚点与容器布局
- 02参考分辨率缩放
- 03适配安全区域的布局
- 04键盘与手柄焦点导航
- 05基于栈的屏幕流程
- 06事件驱动的 HUD 更新
适用场景
- 01构建适配多种屏幕的 HUD
- 02让菜单支持手柄导航
- 03组织暂停与设置界面
- 04根据游戏事件更新 HUD
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill game-ui-ux安装后在 Claude Code 中输入/game-ui-ux确认已加载。
附带文件references/layout-and-flow.md
详细介绍
游戏 UI/UX
构建 HUD 和菜单,让它们在手机、超宽屏显示器和电视上都能正确显示,并支持手柄和鼠标操作。本技能负责与引擎无关的 UI 架构——响应式布局、缩放、焦点导航、屏幕流程,以及 UI 与游戏状态的交互方式;具体的控件 API 则交由引擎 UI 技能负责。
何时使用
- 构建 HUD(生命值/弹药/分数)、菜单(主菜单/暂停/设置)、背包或商店界面,或任何叠加界面,并希望它们能正确缩放和导航时。
- 修复在其他分辨率/宽高比下显示异常、忽略刘海/安全区域、无法使用控制器操作,或通过逐帧轮询与游戏状态连接的 UI 时。
- 将屏幕流程(标题 → 游戏 → 暂停 → 设置)组织为堆栈,而不是一团布尔标志时。
**何时不使用:**对于引擎的具体 UI 节点/组件和样式,请使用 godot-ui-control 或 Unity UI(UGUI/UI Toolkit)。对于视觉冲击效果(按钮弹跳、伤害数字、震动),请使用 game-feel。对于分支对话 UI,请使用 dialogue-systems。翻译 UI 字符串属于本地化(重绑定界面请参阅 references/ 和 input-systems)。对于卡牌/棋盘布局的具体需求,card-game 类型会组合使用本技能。
核心工作流
- **选择布局模型:锚点 + 容器,绝不使用绝对像素。**将元素锚定到边缘/角落/中心,并让容器(行、列、网格)排列子项。绝对
(x, y)坐标在遇到第一个新分辨率时就会出问题。 - 为整个 UI 选择缩放策略:使用一个可缩放以适应屏幕的参考分辨率(适用于大多数游戏),再制定其他宽高比下额外宽度/高度的处理策略(加黑边、扩展,或将 HUD 角落向外锚定)。
- **遵循安全区域。**让关键 UI 与屏幕边缘保持一定距离,避免刘海、圆角和电视过扫描将其裁切。
- **确保每个屏幕都能通过键盘/手柄导航。**为每个屏幕设置初始焦点控件,定义焦点顺序/邻接关系,并清晰显示焦点高亮。鼠标和焦点导航必须能共存。
- **将屏幕建模为堆栈。**压入新屏幕(在游戏上方显示暂停界面)、弹出屏幕(恢复游戏),并将输入权限与可见性交给顶层屏幕。这样叠加界面和“返回”操作都很简单。
- **通过事件驱动 HUD,而不是轮询。**HUD 订阅
health_changed、score_changed等事件,并仅在事件触发时更新,而不是每帧读取游戏状态。 - **在不同屏幕和设备上验证。**调整窗口大小、切换宽高比、拔掉鼠标后仅用手柄导航,并确认焦点、缩放和安全区域边距。报告你在各个分辨率下实际观察到的情况。
模式
1. 使用锚点 + 容器,而不是绝对坐标
# Godot 4.7. Anchor a HUD label to the TOP-LEFT; let a container flow a row of hearts.
func _ready() -> void:
$Score.set_anchors_preset(Control.PRESET_TOP_LEFT) # sticks to the corner at any size
# An HBoxContainer auto-lays-out children left-to-right; never position hearts by hand.
for i in lives:
$Hearts.add_child(make_heart()) # HBoxContainer spaces them for you
# Unity 6.3 LTS uGUI: set RectTransform anchors to the corner; use a HorizontalLayoutGroup.
# RIGHT: anchors + layout groups. WRONG: rect.anchoredPosition = new Vector2(640, 360) (1080p-only).
2. 缩放至参考分辨率(一个 UI,适配多个屏幕)
# Godot 4.7 — Project Settings > Display > Window > Stretch:
# Mode = "canvas_items", Aspect = "expand", reference size e.g. 1920x1080.
# UI scales to the window; "expand" reveals extra space you anchor HUD corners into.
# Unity 6.3 LTS — Canvas > CanvasScaler:
# UI Scale Mode = "Scale With Screen Size", Reference Resolution = 1920x1080,
# Match = 0.5 (blend width/height) — pick 1.0 if your HUD is height-critical.
3. 为刘海/过扫描设置安全区域边距
# Godot 4.7. Inset a margin container to the OS-reported safe rect (phones, TVs).
func _apply_safe_area() -> void:
var safe: Rect2i = DisplayServer.get_display_safe_area()
var win := DisplayServer.window_get_size()
$Margin.add_theme_constant_override("margin_left", safe.position.x)
$Margin.add_theme_constant_override("margin_top", safe.position.y)
$Margin.add_theme_constant_override("margin_right", win.x - safe.end.x)
$Margin.add_theme_constant_override("margin_bottom", win.y - safe.end.y)
# Unity 6.3 LTS: read Screen.safeArea (Rect in pixels) and set a panel's anchorMin/anchorMax to
# safeArea.position / (position+size) normalized by Screen.width/height.
4. 手柄/键盘焦点(没有焦点导航,控制器就无法操作 UI)
# Godot 4.7. Give each screen a default focus and wire neighbors so a stick/d-pad walks it.
func _on_screen_shown() -> void:
$PlayButton.grab_focus() # always focus SOMETHING on open
$PlayButton.focus_neighbor_bottom = $SettingsButton.get_path()
$SettingsButton.focus_neighbor_top = $PlayButton.get_path()
# Unity 6.3 LTS: EventSystem.SetSelectedGameObject(playButton) on enable; set each Selectable's
# Navigation (Explicit or Automatic). RIGHT: a control is focused on open. WRONG: nothing
# selected → the gamepad does nothing and the player is stuck.
5. 事件驱动 HUD(让 UI 与游戏逻辑解耦)
# RIGHT: HUD reacts to a signal; it updates only when health actually changes.
func _ready() -> void:
player.health_changed.connect(_on_health_changed) # emitted by gameplay
func _on_health_changed(current: int, max: int) -> void:
$HealthBar.value = float(current) / max
# WRONG: func _process(dt): $HealthBar.value = player.hp / player.max_hp # polls every frame,
# couples UI to the player's internals, and runs work even when nothing changed.
常见问题
- 绝对像素位置/单一设计分辨率。 在你的显示器上看起来没问题,在其他地方却会出错。应锚定到边缘或中心,并随容器布局。
- 没有纵横比策略。 仅适用于 16:9 的布局在超宽屏和手机上会严重裁切或出现黑边。决定是扩展还是加黑边,并将 HUD 锚定到会向外移动的角落。
- 忽略安全区域。 HUD 被刘海遮挡,或被电视过扫描裁掉。将关键元素向内缩进。
- 没有初始焦点/没有焦点邻居。 游戏手柄无法正常操作游戏;玩家进入菜单时没有任何选项被选中。始终让一个控件获得焦点,并定义导航方式。
- 在
_process/Update中轮询游戏状态。 这会让 UI 与内部实现紧密耦合,并浪费资源。通过信号/事件推送更新。 - 固定字号太小。 在远距离观看的电视或小屏手机上难以阅读。让文字随 UI 缩放,并提供字号选项。
- 用布尔标志管理菜单流程(
isPaused、inSettings等)会变得难以管理。使用可推入/弹出的屏幕栈。 - 将硬编码的英文字符串写入布局。 翻译后的文字会溢出按钮。将字符串外置,并让容器根据内容调整尺寸(参见
references/)。 - 仅支持鼠标或仅支持焦点操作。 两者都要支持;切换输入设备时不应让用户陷入困境。
参考资料
- 有关各引擎的拉伸/缩放模式、安全区域计算、完整的焦点导航与屏幕栈模式、沉浸式与非沉浸式 UI、无障碍功能(字号、对比度、适合色盲用户的状态显示),以及支持本地化的布局,请阅读
references/layout-and-flow.md。
相关技能
godot-ui-control、Unity UI(UGUI/UI Toolkit)——具体的控件、主题和样式。game-feel——按钮弹跳、过渡效果,以及叠加在此布局之上的 HUD 活力效果。dialogue-systems——构建在此 UI 外壳中的对话/选项 UI。input-systems——设备切换、按键重绑定界面和无障碍控件。rpg、card-game、tower-defense、visual-novel——适合组合使用此技能的重 UI 类型游戏。
评论
支持 Markdown