Luna UI's responsive system applies a breakpoint USS class (e.g. .breakpoint-lg) to the root of every registered UIView from one call. Author breakpoint-prefixed style rules in your USS, then drive the active breakpoint at runtime — your settings UI, an aspect-ratio listener, or a manual button all use the same API.

Quick start

  1. Create the assetAssets > Create > CupkekGames/Luna UI/Responsive Switcher. This produces a ResponsiveViewStyleSwitcher SO.
  2. Wire it on LunaUIManager — assign the SO to the Responsive Switcher field on your scene's LunaUIManager component. (Empty by default; the system is a no-op until wired.)
  3. Author breakpoint-prefixed USS:
    css
    .my-card { width: 100%; } .breakpoint-md .my-card { width: 50%; } .breakpoint-lg .my-card { width: 33%; }
  4. Switch breakpoints at runtime:
    csharp
    LunaUIManager.Instance.ResponsiveSwitcher.SetBreakpoint("lg"); // → adds `.breakpoint-lg` to every UIView's root

Pass empty / null to clear: SetBreakpoint(""). Switching swaps the class cleanly — the previous breakpoint class is removed before the new one is added.

How it works

  • ResponsiveViewStyleSwitcher is a project-wide ScriptableObject. It tracks the currently-applied breakpoint name and dispatches add/remove calls to LunaUIManager.AddClassToAllUIViews / RemoveClassFromAllUIViews.
  • The class prefix is configurable on the SO (_breakpointClassPrefix, default breakpoint-). Change it once per project; call sites pass just the suffix (lg, md, etc.).
  • Subscribe to BreakpointChanged to react to switches:
    csharp
    switcher.BreakpointChanged += name => Debug.Log($"now at {name}");
  • Runtime state is [NonSerialized] — a fresh play session starts with no class applied, so leftover state from a previous session can't desync the live views.

Choosing a naming scheme

The prefix + suffix combination is open. Two common patterns:

PatternExample USSWhen
Tailwind-style.breakpoint-sm, .breakpoint-md, .breakpoint-lg, .breakpoint-xl, .breakpoint-2xlWant familiar mental model; mirrors web.
Device-class.breakpoint-mobile, .breakpoint-tablet, .breakpoint-desktopCare about device categories more than exact widths.

The package doesn't enforce either — you choose the suffixes that make sense for your game.

Driving the breakpoint

The switcher is decoupled from what decides the breakpoint. Wire it to whichever signal fits:

  • Settings UI — let players pick a breakpoint in your settings menu (useful for accessibility / scaling).
  • Aspect-ratio / window-size listener — subscribe to a resize event, map width thresholds to suffixes, call SetBreakpoint.
  • Platform / device — set once at startup based on Application.isMobilePlatform or your own probe.
  • Per-scene — call SetBreakpoint in scene-load logic for fixed-layout scenes.

Sample

The Showcase sample includes ResponsiveDemo (Components/ResponsiveDemo/Scenes/ResponsiveDemo.unity). It exercises the full xs / sm / md / lg / xl / 2xl Tailwind-style ladder with control-bar buttons and a simulated-viewport preview. The driving controller is ResponsiveDemoController.cs.

The flagship FullScreenExamples demo (GameUiHub) also drives breakpoints to switch its tab/modal layout responsively.

GridView responsive variants — GridView/ListView/ListViewResponsiveDemo and GridView/Pagination/PaginationResponsiveDemo — show how list/grid layouts pick up breakpoint classes for column-count changes.

API reference

csharp
// Singleton SO (assigned on LunaUIManager) public class ResponsiveViewStyleSwitcher : ScriptableObject { public string CurrentBreakpoint { get; } // empty string when none public event Action<string> BreakpointChanged; // fires on every change public void SetBreakpoint(string breakpointName); // pass "" / null to clear }

The class prefix and current breakpoint live on the SO; the rest of the work is plain UIView class management. There is no per-frame cost — work happens only on SetBreakpoint calls.

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