Develop

DebugUI sample overview

Updated: May 7, 2026

Overview

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.

What you will learn

  • 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

Requirements

  • Meta Quest device
  • Unity 2022 or later with Meta XR Core SDK
  • See the Meta Quest development setup guide for platform configuration

Get started

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.

Explore the sample

The sample is organized into two layers: reusable core utilities in Core/DebugUI/ and a usage demonstration in Usage/DebugUI/.
File / SceneWhat it demonstratesKey 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

Runtime behavior

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.

Key concepts

Singleton builder API

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.

Multi-pane layout

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 button grouping

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.

VR laser pointer input

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.

Show/Hide lifecycle

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.

Extend the sample

  • 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