Topic 7 · UI
Pitfalls: UI screens & modals
Late-built widgets, hidden screens that still take taps, modal stacks.
Generalized pitfalls from shipped and active projects. Record your own project's traps the same way: Keeping a project pitfall file. All entries LOCKED evidence. Status: locked (empirical, seen in shipped/active projects).
- BIND-AFTER-BUILD — widgets created after the binding pass are never wired. Why: binding walked the tree once, before the late children existed. Check: build the whole tree, then bind; or bind each widget at creation. A clickability test presses every button. Status: locked (empirical, seen in shipped/active projects).
- AUDIT-THE-PANEL-YOU-SHIP — locate the UI root by explicit reference, never by "find any". Why: several documents existed; "any" picked the wrong one. Check: audits take the document/panel by name or reference and assert a non-zero element count. Status: locked (empirical, seen in shipped/active projects).
- SETTLE-ON-A-SIGNAL-NOT-A-FRAME-COUNT — waiting N frames after a UI change can measure the previous layout. Why: layout resolution timing varies (and an unfocused editor may not tick). Check: wait on
GeometryChangedEventor a resolved-style condition, with a timeout. Status: locked (empirical, seen in shipped/active projects).
- LATER-INIT-CAN-UNDO-A-SETTING — a boot
Awakecan overwrite a setting a later owner applied (e.g. orientation lock). Why: two owners wrote the same global. Check: one owner per global setting; grep for every writer. Status: locked (empirical, seen in shipped/active projects).
- MODAL-ROUTER-MUST-STACK — a single-slot modal router swallows the modal a gate is pushed over. Why: the router held one modal, not a stack. Check: modal routing is a stack (or queue) and closing restores the previous entry. See also "Timed release gates: success must dismiss them" (the UI Toolkit runtime page). Status: locked (empirical, seen in shipped/active projects).
- CLAMP-TRUNCATES-A-TRANSITION — a min/max clamp on an animated property can cut its transition to one frame. Why: the clamp, not the transition, drove the visible value. Check: clamp the target, not the in-flight value; record the property over the transition and assert intermediate values. Status: locked (empirical, seen in shipped/active projects).
- AUDIT-AT-THE-SHIPPING-PANEL-SIZE — layout audits must run at the device panel size, not the editor's. Why: the audit used whatever Game view size was open. Check: audits set the panel/reference resolution explicitly per target device. Status: locked (empirical, seen in shipped/active projects).
- OVERLAY-UI-IS-NOT-IN-CAMERA-CAPTURES — screen-space UI Toolkit overlays do not appear in camera renders. Why: overlay panels are composited after camera rendering. Check: capture the Game view/screen (or render the panel to a RenderTexture) when UI is the subject. Status: locked (empirical, seen in shipped/active projects).
- WINDOWS-ONLY-EDITOR-TYPES-BREAK-OTHER-HOSTS — an editor script using a Windows-only type breaks compilation on macOS (and every build from that machine). Why: no platform guard. Check: guard platform APIs with
UNITY_EDITOR_WIN/UNITY_EDITOR_OSX; CI compiles on every host OS. Status: locked (empirical, seen in shipped/active projects).