game-ui-ux

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Game UI/UX

游戏UI/UX

Build HUDs and menus that stay correct on a phone, an ultrawide monitor, and a TV across a gamepad and a mouse. This skill owns the engine-neutral UI architecture — responsive layout, scaling, focus navigation, screen flow, and how UI talks to game state — and defers the concrete widget API to the engine UI skill.
构建可在手机、超宽显示器和电视上,适配游戏手柄与鼠标操作的HUD和菜单。本技能涵盖与引擎无关的UI架构——响应式布局、缩放、焦点导航、屏幕流程,以及UI与游戏状态的交互方式——具体的组件API则交由对应引擎的UI技能处理。

When to use

使用场景

  • Use when building a HUD (health/ammo/score), a menu (main/pause/settings), an inventory or shop screen, or any overlay, and you want it to scale and navigate correctly.
  • Use to fix UI that breaks at other resolutions/aspect ratios, ignores notches/safe areas, can't be used with a controller, or is wired to game state by per-frame polling.
  • Use to structure screen flow (title → game → pause → settings) as a stack, not flag soup.
When not to use: for the engine's concrete UI nodes/components and styling, use
godot-ui-control
or Unity UI (UGUI/UI Toolkit). For visual punch (button pop, damage numbers, shake) use
game-feel
. For branching conversation UI use
dialogue-systems
. For translating UI strings, that is localization (see
references/
and
input-systems
for rebinding screens). For card/board layout specifics, the
card-game
genre composes this skill.
  • 当你需要构建HUD(生命值/弹药/分数显示)、菜单(主菜单/暂停菜单/设置菜单)、物品栏或商店界面,或任何覆盖层,且希望其能正确缩放与导航时使用。
  • 当你需要修复在其他分辨率/宽高比下失效、忽略刘海/安全区域、无法用控制器操作,或通过逐帧轮询关联游戏状态的UI时使用。
  • 当你希望将屏幕流程(标题页→游戏→暂停→设置)构建为栈结构,而非杂乱的标志位时使用。
不适用场景:如需使用引擎的具体UI节点/组件与样式,请使用
godot-ui-control
或Unity UI(UGUI/UI Toolkit)。如需实现视觉冲击力(按钮弹窗、伤害数值、震动效果),请使用
game-feel
。如需分支对话UI,请使用
dialogue-systems
。如需翻译UI字符串,请使用本地化功能(参考
references/
input-systems
进行界面重绑定)。如需卡牌/棋盘布局的具体实现,请结合
card-game
类型技能使用本技能。

Core workflow

核心工作流程

  1. Pick a layout model: anchors + containers, never absolute pixels. Anchor elements to edges/corners/center and let containers (rows, columns, grids) flow children. Absolute
    (x, y)
    positions break at the first new resolution.
  2. Choose a scaling strategy for the whole UI: a reference resolution that scales to fit (most games), plus a policy for extra width/height on other aspect ratios (letterbox, expand, or anchor HUD corners outward).
  3. Respect the safe area. Inset critical UI from screen edges so notches, rounded corners, and TV overscan don't clip it.
  4. Make every screen keyboard/gamepad navigable. Set an initial focused control per screen, define focus order/neighbors, and show a clear focus highlight. Mouse and focus must coexist.
  5. Model screens as a stack. Push (pause over game), pop (resume), with input + visibility handed to the top screen. This makes overlays and "back" trivial.
  6. Drive the HUD from events, not polling. The HUD subscribes to
    health_changed
    ,
    score_changed
    , etc. and updates only when they fire — it does not read game state every frame.
  7. Verify across screens and devices. Resize the window, switch aspect ratios, unplug the mouse and navigate by gamepad only, and confirm focus, scaling, and safe-area insets. Report what you actually observed at which resolutions.
  1. 选择布局模型:锚点+容器,绝对像素不可取。将元素锚定到边缘/角落/中心,让容器(行、列、网格)自动排列子元素。绝对
    (x, y)
    位置在遇到新分辨率时会立即失效。
  2. 为整个UI选择缩放策略:设定一个参考分辨率进行适配(多数游戏采用此方式),同时为其他宽高比的额外宽度/高度制定策略(黑边、扩展或向外锚定HUD角落)。
  3. 尊重安全区域。将关键UI元素与屏幕边缘保持内边距,避免被刘海、圆角或电视过扫描裁剪。
  4. 让每个界面支持键盘/游戏手柄导航。为每个界面设置初始焦点控件,定义焦点顺序/相邻控件,并显示清晰的焦点高亮。鼠标与焦点导航必须共存。
  5. 将界面建模为栈结构。入栈(在游戏上层显示暂停界面)、出栈(恢复游戏),输入与可见性交由栈顶界面处理。这让覆盖层与“返回”操作变得简单。
  6. 通过事件驱动HUD更新,而非轮询。HUD订阅
    health_changed
    score_changed
    等事件,仅在事件触发时更新——无需逐帧读取游戏状态。
  7. 跨界面与设备验证。调整窗口大小、切换宽高比、拔下鼠标仅用游戏手柄导航,确认焦点、缩放与安全区域内边距是否正常。报告你在不同分辨率下实际观察到的情况。

Patterns

设计模式

1. Anchors + containers, not absolute coordinates

1. 锚点+容器,而非绝对坐标

gdscript
undefined
gdscript
undefined

Godot 4.x. Anchor a HUD label to the TOP-LEFT; let a container flow a row of hearts.

Godot 4.x. 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
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 uGUI: set RectTransform anchors to the corner; use a HorizontalLayoutGroup.

Unity 6 uGUI: set RectTransform anchors to the corner; use a HorizontalLayoutGroup.

RIGHT: anchors + layout groups. WRONG: rect.anchoredPosition = new Vector2(640, 360) (1080p-only).

RIGHT: anchors + layout groups. WRONG: rect.anchoredPosition = new Vector2(640, 360) (1080p-only).

undefined
undefined

2. Scale to a reference resolution (one UI, many screens)

2. 基于参考分辨率缩放(一套UI适配多屏幕)

text
undefined
text
undefined

Godot 4.x — Project Settings > Display > Window > Stretch:

Godot 4.x — Project Settings > Display > Window > Stretch:

Mode = "canvas_items", Aspect = "expand", reference size e.g. 1920x1080.

Mode = "canvas_items", Aspect = "expand", reference size e.g. 1920x1080.

UI scales to the window; "expand" reveals extra space you anchor HUD corners into.

UI scales to the window; "expand" reveals extra space you anchor HUD corners into.

Unity 6 — Canvas > CanvasScaler:

Unity 6 — Canvas > CanvasScaler:

UI Scale Mode = "Scale With Screen Size", Reference Resolution = 1920x1080,

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.

Match = 0.5 (blend width/height) — pick 1.0 if your HUD is height-critical.

undefined
undefined

3. Safe-area inset for notches / overscan

3. 针对刘海/过扫描的安全区域内边距

gdscript
undefined
gdscript
undefined

Godot 4.x. Inset a margin container to the OS-reported safe rect (phones, TVs).

Godot 4.x. 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)
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: read Screen.safeArea (Rect in pixels) and set a panel's anchorMin/anchorMax to

Unity 6: read Screen.safeArea (Rect in pixels) and set a panel's anchorMin/anchorMax to

safeArea.position / (position+size) normalized by Screen.width/height.

safeArea.position / (position+size) normalized by Screen.width/height.

undefined
undefined

4. Gamepad/keyboard focus (UI is unusable on a controller without it)

4. 游戏手柄/键盘焦点导航(无此功能则控制器无法操作UI)

gdscript
undefined
gdscript
undefined

Godot 4.x. Give each screen a default focus and wire neighbors so a stick/d-pad walks it.

Godot 4.x. 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()
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: EventSystem.SetSelectedGameObject(playButton) on enable; set each Selectable's

Unity 6: EventSystem.SetSelectedGameObject(playButton) on enable; set each Selectable's

Navigation (Explicit or Automatic). RIGHT: a control is focused on open. WRONG: nothing

Navigation (Explicit or Automatic). RIGHT: a control is focused on open. WRONG: nothing

selected → the gamepad does nothing and the player is stuck.

selected → the gamepad does nothing and the player is stuck.

undefined
undefined

5. Event-driven HUD (decouple UI from game logic)

5. 事件驱动HUD(解耦UI与游戏逻辑)

gdscript
undefined
gdscript
undefined

RIGHT: HUD reacts to a signal; it updates only when health actually changes.

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

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.

couples UI to the player's internals, and runs work even when nothing changed.

undefined
undefined

Pitfalls

常见陷阱

  • Absolute pixel positions / a single design resolution. Looks right on your monitor, broken everywhere else. Anchor to edges/center and flow with containers.
  • No aspect-ratio policy. 16:9-only layouts crop or letterbox badly on ultrawide and phones. Decide expand vs letterbox and anchor HUD to corners that move outward.
  • Ignoring the safe area. HUD under a notch or lost to TV overscan. Inset critical elements.
  • No initial focus / no focus neighbors. The game is unplayable on a gamepad; players land on a menu with nothing selected. Always focus one control and define navigation.
  • Polling game state in
    _process
    /
    Update
    .
    Couples UI to internals and wastes work. Push updates via signals/events.
  • Tiny fixed font sizes. Unreadable on a TV-at-distance or a small phone. Scale text with the UI and offer a text-size option.
  • Menu flow as boolean flags (
    isPaused
    ,
    inSettings
    , …) becomes unmanageable. Use a screen stack with push/pop.
  • Hardcoded English strings baked into layout. Translations overflow buttons. Externalize strings and let containers size to content (see
    references/
    ).
  • Mouse-only or focus-only. Support both; switching input device should not strand the user.
  • 绝对像素位置/单一设计分辨率:在你的显示器上显示正常,但在其他设备上完全失效。应将元素锚定到边缘/中心,并通过容器自动排列。
  • 无宽高比策略:仅适配16:9的布局在超宽屏和手机上会严重裁剪或出现黑边。需确定是扩展还是添加黑边,并将HUD锚定到可向外移动的角落。
  • 忽略安全区域:HUD被刘海遮挡或因电视过扫描丢失。需为关键元素设置内边距。
  • 无初始焦点/无焦点相邻控件:游戏无法用游戏手柄操作;玩家进入菜单后无任何选中项。必须在打开界面时聚焦一个控件,并定义导航关系。
  • _process
    /
    Update
    中轮询游戏状态
    :将UI与内部逻辑耦合,且浪费性能。应通过信号/事件推送更新。
  • 固定过小的字体尺寸:在远距离电视或小屏手机上无法阅读。应让文本随UI缩放,并提供字体大小选项。
  • 用布尔标志管理菜单流程
    isPaused
    ,
    inSettings
    等):会变得难以维护。应使用入栈/出栈的屏幕栈结构。
  • 布局中硬编码英文字符串:翻译后的文本会溢出按钮。应将字符串外部化,让容器根据内容自动调整尺寸(参考
    references/
    )。
  • 仅支持鼠标或仅支持焦点导航:需同时支持两种方式;切换输入设备不应导致用户无法操作。

References

参考资料

  • For stretch/scale modes per engine, the safe-area math, a complete focus-navigation and screen-stack pattern, diegetic vs non-diegetic UI, accessibility (text size, contrast, colorblind-safe state), and localization-ready layout, read
    references/layout-and-flow.md
    .
  • 如需了解各引擎的拉伸/缩放模式、安全区域计算、完整的焦点导航与屏幕栈模式、叙事性与非叙事性UI、无障碍功能(字体大小、对比度、色盲友好状态),以及支持本地化的布局,请阅读
    references/layout-and-flow.md

Related skills

相关技能

  • godot-ui-control
    , Unity UI (UGUI/UI Toolkit) — the concrete widgets, themes, and styling.
  • game-feel
    — button pops, transitions, and HUD juice that ride on top of this layout.
  • dialogue-systems
    — conversation/choice UI that lives inside this UI shell.
  • input-systems
    — device switching, rebinding screens, and accessible controls.
  • rpg
    ,
    card-game
    ,
    tower-defense
    ,
    visual-novel
    — UI-heavy genres that compose this skill.
  • 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密集型游戏类型。