Game UI and Menus skill for Codex
Menus that work with a controller in hand. Codex builds menus as a focus-aware screen stack where every screen has a default selection and Back always works, swaps button prompts for the device in use, anchors the HUD inside safe areas across aspect ratios, and ships the settings players expect: rebinding, hold-or-toggle, subtitles and text scaling. It tests with the mouse unplugged and a pseudo-localized string pass.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- game-ui Installs to ~/.agents/skills/game-ui/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install game-ui The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project game-ui Installs to .agents/skills/game-ui/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/game-ui.zipunzip -o game-ui.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) game-ui PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $game-ui, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Builds game HUDs and menus that work with mouse, keyboard, gamepad and touch - focus navigation and default selection, input prompt glyph swapping, resolution and aspect scaling with safe areas, pause and settings screens, key rebinding, subtitles and accessibility options, localization-ready layouts and UI performance - in Unity (UI Toolkit, uGUI), Godot Control nodes, Unreal UMG/CommonUI or web canvases. Use when building a main menu, pause menu, settings or inventory screen, a menu cannot be used with a controller, the HUD breaks on ultrawide or phones with notches, or text overflows after translation.
Use it when
- Building main, pause, settings or inventory screens
- Menus lose focus or are unusable without a mouse
- The HUD breaks at different resolutions, aspect ratios or safe areas
- Preparing UI for localization and accessibility options
Use something else when
- You need web app accessibility auditing rather than game menus: use wcag-accessibility-audit
- The UI frame cost is part of a wider Unity slowdown: use unity-performance
How to check the result
With the mouse unplugged every screen is operable by gamepad, focus never vanishes, and the HUD stays inside safe areas at 16:9, 16:10, 21:9 and a notched phone.
The mistake it prevents
Closing a popup without restoring focus, which leaves controller players with nothing selected and no way to continue.
Done well means: every screen is fully usable with a gamepad alone, keyboard alone, and mouse or touch alone; focus is always visible and never lost; the HUD respects safe areas at 16:9, 21:9, 16:10 and phone aspect ratios; text survives 40% longer translations; and settings, rebinding and subtitles exist before launch, not after reviews ask for them.
Before building
- Read
AGENTS.md, identify the UI tech (Unity UI Toolkit or uGUI, GodotControl, Unreal UMG with or without CommonUI, HTML overlay or canvas) and the target platforms and inputs. - List screens and the flow between them (title, main menu, settings, pause, HUD, inventory, game over). Each screen gets: default focused element, back/cancel behaviour, and what pauses.
- Decide the reference resolution (1920x1080 is common) and scale mode before laying out anything.
Screen stack and back behaviour
- Manage menus as a stack: opening pushes, Back/Cancel (Esc, gamepad B/Circle, Android back) pops. The top screen owns input; screens below do not receive it.
- On push, set focus to the screen’s default element. On pop, restore focus to the element that opened it.
- Pause opens over gameplay and stops simulation time; UI animations use unscaled time
(Unity
Time.unscaledDeltaTime, Godotprocess_mode = PROCESS_MODE_ALWAYSon the menu, Unreal widgets tick while paused unless told otherwise).
Controller and keyboard focus
| Engine | Focus API | Navigation |
|---|---|---|
| Unity uGUI | EventSystem.current.SetSelectedGameObject(button) | Selectable.navigation (Automatic or Explicit) |
| Unity UI Toolkit | element.Focus(), focusable = true | Navigation events (NavigationMoveEvent, NavigationSubmitEvent) |
| Godot | control.grab_focus(), focus_mode = FOCUS_ALL | focus_neighbor_*, focus_next/focus_previous; ui_up/ui_accept actions |
| Unreal UMG | SetUserFocus / SetKeyboardFocus; CommonUI handles focus per activatable widget | Widget navigation rules; CommonUI input routing |
Rules:
- Something is always focused while a menu is open. When the mouse moves, it may take over highlighting; when a stick or arrow key is pressed, focus returns to the last focused element.
- Explicit navigation for grids and irregular layouts; automatic navigation picks surprising neighbours in non-rectangular layouts.
- Wrap or stop at edges consistently. Tabs switch with shoulder buttons (LB/RB, L1/R1).
- Focus visuals: a strong outline or scale change, not only a colour change (colour-blind players).
- Disable or hide elements properly; a disabled button that can still be focused confuses players.
# Godot: open a menu with correct focus and restore it on close
func open_menu(menu: Control, opener: Control) -> void:
_focus_stack.push_back(opener)
menu.show()
menu.get_node("%DefaultButton").grab_focus()
func close_menu(menu: Control) -> void:
menu.hide()
var back_to: Control = _focus_stack.pop_back()
if is_instance_valid(back_to) and back_to.is_visible_in_tree():
back_to.grab_focus()
Input prompts
- Track the last used device type (keyboard/mouse, Xbox, PlayStation, Switch, touch) and swap prompt glyphs live. Show the actual bound key, read from the rebinding system, not a hard-coded “Press E”.
- Glyphs come from one lookup table keyed by action and device family. Unity Input System:
action.GetBindingDisplayString(...); Godot: inspectInputMap.action_get_events. - Platform certification on consoles requires correct platform-specific button names and icons; confirm with the platform’s guidelines (under NDA, the user must check).
Layout, scaling and safe areas
| Concern | Approach |
|---|---|
| Different resolutions | Scale UI from a reference resolution (Unity Canvas Scaler “Scale With Screen Size”, match 0.5; Godot content_scale_mode = canvas_items with aspect = expand; UMG DPI curve) |
| Different aspect ratios | Anchor HUD elements to corners and edges, not absolute positions; test 16:9, 16:10, 21:9, 4:3 |
| TV overscan and phone notches | Keep critical HUD inside the safe area: Unity Screen.safeArea, Godot DisplayServer.get_display_safe_area(), CSS env(safe-area-inset-*) |
| Readability | Minimum text height about 28 px at 1080p for TV distance (console guidance varies; check platform requirements) |
| Text scale option | Allow 100-150%+ and let layouts grow (auto-size containers, scrolling lists) |
Settings that should exist
- Audio: master, music, effects, voice sliders (store linear 0-1, convert to dB for mixers:
20 * log10(max(v, 0.0001))). - Video: resolution, window mode, VSync, frame-rate cap, quality preset, brightness/gamma.
- Controls: full rebinding for keyboard and gamepad, sensitivity, invert Y, hold vs toggle for sprint/aim/crouch.
- Accessibility: subtitles (size, background, speaker names), colour-blind safe UI (do not rely on colour alone), reduced camera shake/flash, text size, screen reader or narration where feasible.
- Apply settings live with a preview, confirm display changes with a revert timer (10 s).
- Persist settings separately from save games (see game-save-systems).
Localization-ready UI
- All strings come from a string table keyed by ID; no concatenated sentences (
"You have " + n + " coins"). Use templated strings with plural rules (ICU-style or the engine’s localization package). - Leave 30-40% extra width; German and Finnish run long, CJK needs fonts with the glyphs.
- Font fallback chains for CJK, Cyrillic, Arabic; right-to-left layouts need mirrored UI.
- Test with a pseudo-localization pass (accented, 40% longer strings) before real translations.
HUD design rules
- Show only what decisions need. Diegetic or contextual elements (ammo near the crosshair, health fading in when damaged) beat permanent panels.
- Damage direction indicators, hit markers and low-health warnings need both visual and audio cues.
- Never block the centre of the screen with persistent UI in action games.
UI performance
- Unity uGUI: split frequently changing elements onto separate canvases; disable Raycast Target on non-interactive graphics. UI Toolkit: avoid rebuilding the visual tree each frame; update labels only when values change.
- Update text only on value change, not every frame; cache formatted strings for counters.
- Web/canvas overlays: avoid layout thrash; batch DOM updates per frame.
Verification
- Unplug the mouse: every screen reachable and operable with a gamepad, including rebinding
- Keyboard only: Tab/arrows/Enter/Esc work everywhere
- Focus never disappears after closing a popup, changing tabs or disabling a button
- HUD checked at 1280x720, 1920x1080, 2560x1080 (21:9), 1920x1200 and a notched phone
- Pseudo-localized strings fit or scroll; no clipped text
- Settings persist across restarts and invalid stored values fall back to defaults
- Pause menu stops gameplay time and its own animations still run
Hand-off summary
**Screens:** Title, Main, Settings (Audio/Video/Controls/Accessibility tabs), Pause, HUD
**Focus:** default element per screen, restore-on-close stack, explicit navigation on the inventory grid
**Prompts:** glyph table for KBM/Xbox/PlayStation/Switch, swaps on last device used
**Scaling:** reference 1920x1080, safe-area container for HUD, tested 5 aspect ratios
**Accessibility:** subtitles with size/background, hold-to-toggle options, reduce flashes
**Open:** console-specific glyph compliance must be checked against platform guidelines What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "Game UI and Menus"
short_description: "Menus that work with a controller in hand"
default_prompt: "$game-ui Our pause and settings menus cannot be used with a gamepad, fix the focus navigation" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.