DebugUI sample overview
Updated: May 7, 2026
This sample demonstrates a runtime debug panel system for Meta Quest VR applications using the DebugUIBuilder utility. The implementation showcases a reusable UI builder with buttons, sliders, toggles, and radio buttons for in-headset configuration, VR-optimized laser pointer input, and automatic controller detection.
- Using the DebugUIBuilder singleton API to create runtime debug panels with minimal code
- Implementing a VR laser pointer with
OVRCursor for world-space UI interaction - Organizing debug UI elements across multiple panes and tabs
- Detecting and routing input from the active controller with handed input selection
- Wiring callbacks for buttons, sliders, toggles, and radio button groups
- Meta Quest device
- Unity 2022 or later with Meta XR Core SDK
- See the Meta Quest development setup guide for platform configuration
The sample is part of the Unity-StarterSamples repository on GitHub. After opening the project in Unity, you access the DebugUI sample through the StartScene browser. The debug panel appears immediately when you run the sample; the B button toggles visibility. Refer to the repository README for build and deployment steps.
The sample is organized into two layers: reusable core utilities in Core/DebugUI/ and a usage demonstration in Usage/DebugUI/.
| File / Scene | What it demonstrates | Key concepts |
|---|
DebugUISample.cs | All widget types (button, label, slider, toggle, radio, divider) and multi-pane layout | Singleton builder API, callback wiring, runtime show/hide |
DebugUIBuilder.cs | Prefab-based UI construction, panel positioning, and lifecycle management | Singleton pattern, OVRCameraRig-relative positioning, Show/Hide state |
LaserPointer.cs | VR laser pointer extending OVRCursor | Custom cursor implementation, beam visualization, input focus |
HandedInputSelector.cs | Active controller detection and raycast routing | Hand anchor selection, automatic left/right switching |
Prefabs (10 files) | UI element templates and canvas structure | Prefab instantiation, Canvas configuration |
When you run the sample, a debug panel appears in front of you showing buttons, sliders, toggles, and radio buttons across three panes. A laser beam extends from your active controller, allowing you to point at and interact with UI elements. Clicking the button logs “Button pressed” to the console. Moving the slider updates its displayed value and logs the new value. Toggling the checkbox or selecting radio buttons logs their state changes. Pressing the B button on your controller hides the panel; pressing B again makes it reappear.
The sample uses DebugUIBuilder.instance to access the builder from any script. Notice how DebugUISample.cs adds all widgets in a single Start() method:
DebugUIBuilder.instance.AddButton("Button Pressed", LogButtonPressed);
DebugUIBuilder.instance.AddSlider("Slider", 1.0f, 10.0f, SliderPressed, true);
Each AddX method returns a RectTransform, allowing you to further configure positioning if needed. See the complete implementation in Usage/DebugUI/DebugUISample.cs.
The builder organizes widgets across three panes: center, secondary tab, and right. The sample routes elements to different panes using the targetCanvas parameter:
AddLabel("Secondary Tab", 1); // Pane 1
AddRadio("Side Radio 1", "group2", delegate(Toggle t) { ... }, DEBUG_PANE_RIGHT); // Right pane
Panes with no elements automatically hide. This pattern allows you to organize debug controls by category or use case. The pane constants (DEBUG_PANE_CENTER, DEBUG_PANE_RIGHT, DEBUG_PANE_LEFT) are defined in DebugUIBuilder.cs.
Radio buttons use string-based groups to ensure mutual exclusivity. The sample creates two groups: one in the center pane and one in the right pane. The first radio button added to a group is automatically selected. Toggle groups are managed internally by Unity’s UI system, but the builder handles prefab instantiation and wiring. See the radio setup logic in Core/DebugUI/Scripts/DebugUIBuilder.cs.
LaserPointer.cs extends OVRCursor to provide a visual beam from the controller to UI elements. The beam visibility changes based on interaction state — visible when hitting a UI target, hidden otherwise — and uses Unity’s raycasting system to detect targets. HandedInputSelector automatically switches the laser pointer between left and right controller anchors based on which controller is active, so users can interact with either hand.
The builder’s Show() method positions the panel relative to the OVRCameraRig (preserving Y-rotation only) and activates the laser pointer. Hide() deactivates the panel and restores the previous state. The sample toggles visibility by monitoring OVRInput.Button.Two (B button) in its Update() loop. This pattern allows you to show debug UI only when needed, reducing visual clutter during normal gameplay.
- Add custom widgets to the builder by creating new prefabs and
AddX methods, following the existing patterns for button, slider, and toggle - Integrate the DebugUIBuilder into your own project to expose runtime configuration (physics parameters, rendering options, AI settings)
- Explore the
AddTextField method (present in the API but not demonstrated in this sample) for text input scenarios - Study how other samples in the repository use DebugUIBuilder — five other samples use it, including StartMenu,
OVROverlaySample, LocomotionSampleSupport, and Firebase integration samples