A stack keeps every open view alive — and by default UI Toolkit keeps rendering all of them, even the ones fully covered by the screen on top. Occlusion is the per-destination policy that decides what happens to the views beneath a destination while it's on top of its stack. It's one dropdown on the NavNode.

ModeBeneath, during the transitionBeneath, once settledUse for
Overlay (default)visiblevisible — keeps renderingmodals, toasts, anything see-through
Replacehiddenhidden — popped-style hidescreen-replaces-screen flows
Overlay Opaquevisibledisplay:none — stops rendering, stays openfull-screen takeovers with a solid background

Occlusion is scoped to the destination's own stack and is ignored for tabs — switching governs a tab's visibility, not occlusion.

Overlay

The default. The view below stays visible and keeps rendering for as long as the new view sits on top. Correct for anything the user can see through — dim-backdrop modals, toasts, partial overlays — and the right default for everything else, because it can't be visually wrong. Its only cost is performance: a fully covered screen still pays render cost every frame.

Replace

The view beneath is hidden (same visual path as a pop) as the new view pushes in, and shown again when the top view leaves. Use it when the incoming screen conceptually replaces the one below and you want the old screen to fade away during the transition — the two views crossfade, so the swap reads as a scene change, not a cover.

Because the view below runs a real hide, its fade events fire (OnFadeOutStart / OnFadeOut) and its input is released like any hidden view.

Overlay Opaque

A render optimization for destinations whose solid background fully covers the screen — a fullscreen inventory over a hub, a settings screen over a pause menu. It behaves like Overlay during transitions and like "stop drawing everything under me" at rest:

  1. Push — views beneath stay visible while the new view animates in, exactly like Overlay. No seams, any transition style works.
  2. Settled (fade-in completes) — every view rendered beneath it in its own stack flips to display:none. With UI Toolkit that means zero render, zero layout, zero style-evaluation cost for the covered screens.
  3. Hiding (fade-out starts — for any reason: pop, Esc, Close, ReplaceTop, a cascade, a channel switch) — the covered views are restored before the outgoing animation runs, so the user always sees live UI behind the departing screen.

The covered views stay logically open the whole time: they keep their stack position, their element state (scroll positions, text fields, animators), and — because display:none doesn't stop UI Toolkit bindings — their data bindings keep updating. No lifecycle events fire on them; the reveal is instant and data-fresh. Expect a one-frame layout recalculation on the frame they come back.

Push ──► transition (beneath visible) ──► settled: beneath display:none Pop / Close / ReplaceTop / channel switch ──► hide starts: beneath restored ──► transition plays over live UI

Scope — what exactly gets occluded

  • Everything rendered beneath it in its own stack, not just the frame directly under it.
  • A root-stack Overlay Opaque also occludes the active channel stacks beneath it. The root stack layers above tab content, so a fullscreen takeover pushed to the root (the common case — a forest-root node) turns off the tab shell and the active tab's frames.
  • Nested opaques unwind correctly. Each occluder only flips views that were actually rendering when it settled, and restores exactly that set when it leaves — stacking two fullscreen screens and popping them one at a time reveals layer by layer.

When not to use it

Anything beneath visibly vanishes the instant the top view settles — so this mode is only correct when the user genuinely cannot see behind the view:

  • Any transparency in the background — gradients with alpha, blur, cutouts, rounded corners revealing the screen behind.
  • Nodes with a backdrop. A Dim or Custom backdrop exists to show the screen behind; that's Overlay by definition.
  • Partial coverage — centered windows, side sheets, anything that doesn't fill the panel on every breakpoint / aspect ratio you ship.
  • Views over a live 3D scene where the UI is the only cover — occlusion hides UI beneath; the world camera keeps rendering regardless.

When in doubt, leave the default. Overlay is never visually wrong; Overlay Opaque saves cost only when the cover is total.

Authoring

Set Occlusion = Overlay Opaque on the NavNode. The canvas badges it opaque (purple), next to replace / backdrop / seed / multi.

The samples use it where it's valid, if you want live references: in Showcase, the six fullscreen screens over the hub (inventory, mailbox, journeypass, profile, chat, hero.detail); in GameFull, the settings screen. The pause menu and the GameFull inventory deliberately stay Overlay — both use a dim backdrop over the game.

There's also a dedicated stress demo: Showcase/Components/Occlusion/OcclusionDemo.unity stacks three Overlay Opaque screens on a base screen, each with a live timer plus text / toggle / slider / scroll state. Push to the deepest layer, then pop back down — every layer reveals with its timer current and its state untouched, which is the multi-depth state-preservation guarantee in action.

Verifying the win

Open the Frame Debugger (or the Profiler's UI Toolkit markers), settle a fullscreen Overlay Opaque, and watch the draw calls for the covered screens disappear. The canvas runtime overlay still shows the covered frames as stacked — occlusion is render-only and doesn't change nav state.

Advanced — the underlying switch

Navigation drives occlusion through UIView.SetRenderOccluded(bool) — a pure display toggle that leaves visibility state, input blocking, and fade state untouched (UIView.IsRenderOccluded reads it back). It's public if you need the same render-only hiding outside the nav stack, but inside a graph, prefer the node policy: the stack handles every reveal path (pop, cascade, replace, channel switches, teardown) for you.

See also

  • Navigation — the stack, graph authoring, and the full NavNode field reference
  • FadeUIElement — the fade events (OnFadeIn, OnFadeOutStart) occlusion keys off
  • UIView — visibility, input blocking, and the render-occlusion switch

Reading along without the package? Occlusion ships with the nav system in Luna — get it on the Asset Store.

Settings

Theme

Light

Contrast

Material

Dark

Dim

Material Dark

System

Sidebar(Light & Contrast only)

Light
Dark

Font Family

DM Sans

Wix

Inclusive Sans

AR One Sans

Direction

LTR
RTL