Adopt Luna in an Existing UITK Project

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.

StageWhat you getWhat you touch
0. InstallLuna in the project, nothing changedPackage Manager, one prefab
1. ThemeYour existing UI restyled by Luna's design systemOne Panel Settings reference, or one @import
2. Components + featuresLuna widgets, effects, text animation, tooltips, inline 3D inside your existing screensYour UXML / your C# tree building
3. Views + navigationThe full workflow: view prefabs, nav graph, fades, focus, occlusionOne screen at a time

Stage 0: install

The minimal footprint from Quick Start:

  1. Install Luna from the Asset Store. All bundled dependencies come with it, no manifest edits.
  2. Import only the Essentials sample (the design system + bootstrap kit). Showcase and GameFull are demo content, never required.
  3. Drag 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.

Stage 1: theme your existing UI

Luna's whole look arrives through one reference. Pick the route that matches your setup:

  • You are fine adopting Luna's Panel Settings: point your existing renderer's Panel Settings field at Essentials/Theme/LunaPanelSettings.asset (or the WorldSpace variant). Done.
  • You need to keep your own Panel Settings (custom scale mode, render target): open your Theme StyleSheet and @import Luna's main theme instead:
css
@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 style values (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.

Stage 2: Luna components and features, your screens

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.

  • Custom controls: ProgressBar, TabView, Tooltip, RadialLoading, Pagination and the rest of the component set. Drop them in from the UI Builder Library, write them in UXML with the luna: prefix, or construct them from C# like any VisualElement.
  • Text Effects: wave, shake, rainbow, typewriter reveals on any Label. No view infrastructure involved.
  • Interaction Juice and Transition Animation presets: hover/press feel and entrance animations on your existing elements.
  • UI Effects: glow, outline, shadow, gradient, pattern from the Essentials filter shader assets, no textures needed.
  • UI Render: inline 3D (characters, items, particles) inside your UI. Needs the UIRenderManager in the scene; it self-drives when nothing else ticks it.
  • UI Attractor: fly-to-target collect effects. The LunaUIManager from Stage 0 drives it.
  • Spotlight: cutout + caption onboarding tours over whatever UI you already have.

Some of these read best-quality settings (Spotlight's soft feather, UI audio) from the LunaUIManager in your scene. That prefab is the one piece of Luna infrastructure this stage leans on, and you placed it in Stage 0.

Stage 3: adopt the view + navigation workflow

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:

  1. Make the screen a view prefab: a GameObject with a 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).
  2. Keep your controller logic. Your existing MVC controller class becomes the 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.
  3. Add the screen to a nav graph and let a NavHost spawn it. From other code, open it by id.
  4. Show and hide through the stack, not through inline display toggles. Fades, focus, and occlusion all key off the stack lifecycle.

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.

Doing this with an AI agent

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)

Light
Dark

Font Family

DM Sans

Wix

Inclusive Sans

AR One Sans

Direction

LTR
RTL