This page is for projects that already have UI Toolkit screens: your own UXML and USS, or UI built entirely from C#. Coming from uGUI instead? Start at Migrate from uGUI to Luna, which lands back here for the shared stages.
Migrating a project with 10+ screens to Luna in one sitting is not realistic, and you do not have to. Adoption is staged: each stage ships visible value on its own, your existing screens keep working throughout, and you decide when to take the next step. The recommended end state is the full Luna workflow (views, navigation, focus management), because that is where the fades, controller support, occlusion, and stack handling live. The stages are how you get there without stopping feature work.
| Stage | What you get | What you touch |
|---|---|---|
| 0. Install | Luna in the project, nothing changed | Package Manager, one prefab |
| 1. Theme | Your existing UI restyled by Luna's design system | One Panel Settings reference, or one @import |
| 2. Components + features | Luna widgets, effects, text animation, tooltips, inline 3D inside your existing screens | Your UXML / your C# tree building |
| 3. Views + navigation | The full workflow: view prefabs, nav graph, fades, focus, occlusion | One screen at a time |
The minimal footprint from Quick Start:
Assets/Samples/LunaUI/<version>/Essentials/Prefabs/LunaUIManager.prefab into your scene and make sure an EventSystem exists. The manager drives focus, input, UI audio, and the per-frame ticking some features use.Nothing about your existing UI changes yet.
Luna's whole look arrives through one reference. Pick the route that matches your setup:
Essentials/Theme/LunaPanelSettings.asset (or the WorldSpace variant). Done.@import Luna's main theme instead:@import url("/Packages/com.cupkekgames.luna/Runtime/Setup/CupkekGamesMainTheme.tss");
/* your existing rules follow, and win where they overlap */Either way, standard UITK controls (<Label>, <Toggle>, <Slider>, <TextField>, dropdowns, lists) restyle automatically, with one exception: a <Button> only takes the Luna look with an explicit class="btn" (see First View). To make the palette yours, copy the Essentials theme folder and override tokens as described in Theme Stack.
Inline styles block the theme. Inline
stylevalues (set in UI Builder or from C#) always beat stylesheet rules. If your current workflow sets colors and visibility inline, those elements will ignore the theme until the inline values are cleared. Prefer adding and removing USS classes; it is also what keeps a later re-skin a one-file change. The Styling utility classes cover most inline-style habits (spacing, color, layout) with single classes.
Stage 1 is a good place to pause and ship. Nothing structural changed; your UI just looks like a designed product.
Everything in this stage works inside your existing screens, whether they come from UXML or are built in C#. None of it requires converting a single screen to the Luna view workflow.
luna: prefix, or construct them from C# like any VisualElement.UIRenderManager in the scene; it self-drives when nothing else ticks it.LunaUIManager from Stage 0 drives it.Some of these read best-quality settings (Spotlight's soft feather, UI audio) from the
LunaUIManagerin your scene. That prefab is the one piece of Luna infrastructure this stage leans on, and you placed it in Stage 0.
This is the destination, and the part worth doing screen by screen. What it buys you over hand-managed screens: stack-based navigation with escape/controller-B dismissal, automatic fade lifecycles, focus management for gamepad, occlusion (hidden screens stop rendering), and screens as reusable prefabs. The model is documented in Navigation Graph; the authoring loop is First View.
The per-screen recipe:
PanelRenderer (source = the screen's UXML) and your UIViewComponent subclass. Under navigation, leave the prefab's Panel Settings empty; the host's NavConfigSO owns it (Theme Stack).UIViewComponent subclass. Element lookups move into OnUILoaded(VisualElement root) (the tree arrives asynchronously; never query in Awake), get cached once there, and the rest of your controller code stays what it was. If a screen's tree is built in C# rather than UXML, give the prefab a one-container UXML shell and build into root from OnUILoaded; convert to UXML later or never.NavHost spawn it. From other code, open it by id.Migration order for a real project: start with your next new screen (zero conversion cost, immediate feel for the workflow), then modals and popups (small, high reuse, Luna ships Confirmation and Input popups you can adopt outright), then leaf screens, and the shell/root screens last. Luna-hosted views and your legacy screens coexist fine during the whole process; they are separate panels.
Check Views before converting each screen. Settings, Save & Load, Main Menu, Pause, Credits, Inventory, and the dialogue set already exist as extendable views; adopting one is usually faster than porting your own.
The mechanical parts of Stage 3 (UXML-ifying a C#-built tree, moving lookups into OnUILoaded, writing the graph nodes) are exactly the work AI agents are good at. This site publishes agent-readable endpoints for every page; see AI Development for how to point your agent at them and the prompts that work well for this migration.
Settings
Theme
Light
Contrast
Material
Dark
Dim
Material Dark
System
Sidebar(Light & Contrast only)
Font Family
DM Sans
Wix
Inclusive Sans
AR One Sans
Direction