---
title: "Pitfalls: UI screens & modals"
slug: /workflows/pitfalls-ui/
markdown: /workflows/pitfalls-ui.md
section: pitfalls
tier: 2
summary: "Late-built widgets, hidden screens that still take taps, modal stacks."
sources: ['pitfalls/ui.md']
canonical: https://unityworkflowlibrary.dev/workflows/pitfalls-ui/
read_first: /read-first.md
---

> Read first, on every prompt: [non-destructive rules](/read-first.md).

# 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](/workflows/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).

> **Why this rule exists** (BIND-AFTER-BUILD): Buttons built after `Bind` rendered fine and did nothing; the layout audit called the screen clean.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

- **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).

> **Why this rule exists** (AUDIT-THE-PANEL-YOU-SHIP): `FindAnyObjectByType<UIDocument>` returned an empty panel and the audit reported it clean.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

- **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 `GeometryChangedEvent` or a resolved-style condition, with a timeout. Status: locked (empirical, seen in shipped/active projects).

> **Why this rule exists** (SETTLE-ON-A-SIGNAL-NOT-A-FRAME-COUNT): A stress tool waited 4 editor frames and measured the prior step's geometry.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

- **HIDDEN-SCREENS-STILL-PICK — a hidden or "asleep" UI screen can still steal pointer input.** Why: opacity/visibility tricks left `pickingMode` and display active. Check: inactive screens use `display: none` or `pickingMode = Ignore` on their root; a test taps through every visible input. Status: locked (empirical, seen in shipped/active projects).

> **Why this rule exists** (HIDDEN-SCREENS-STILL-PICK): Players could not tap a text field because an inactive screen layered above still received picks.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

- **LATER-INIT-CAN-UNDO-A-SETTING — a boot `Awake` can 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).

> **Why this rule exists** (LATER-INIT-CAN-UNDO-A-SETTING): Portrait lock set in Player Settings and by the UI root was undone by a boot object's `Awake` that ran in a different order.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

- **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](/workflows/ui-toolkit-runtime/) page). Status: locked (empirical, seen in shipped/active projects).

> **Why this rule exists** (MODAL-ROUTER-MUST-STACK): Pushing a connection gate over an open dialog discarded the dialog; closing the gate left nothing.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

- **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).

> **Why this rule exists** (CLAMP-TRUNCATES-A-TRANSITION): A height transition snapped in one frame while other properties animated, because a clamp held the value at its bound until the last frame.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

- **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).

> **Why this rule exists** (AUDIT-AT-THE-SHIPPING-PANEL-SIZE): A layout walk audited at a different reference height than the phone panel, so overflow on device never showed.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

- **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).

> **Why this rule exists** (OVERLAY-UI-IS-NOT-IN-CAMERA-CAPTURES): Verification screenshots taken from a camera showed no UI at all and were misread as a broken screen.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

- **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).

> **Why this rule exists** (WINDOWS-ONLY-EDITOR-TYPES-BREAK-OTHER-HOSTS): An editor helper referencing a Windows-only API compiled on Windows and failed on the Mac build host, blocking the iOS build.
> *Source: Pitfall log of a shipped or active Unity project, generalized.*

