Develop

How to Scroll UI Panels with Microgestures and Gaze

Updated: Aug 20, 2026

Overview

DiscreteScrollInputProvider scrolls a Unity UI ScrollRect in response to discrete directional scroll commands. The component is not tied to microgestures. It exposes ScrollUp, ScrollDown, ScrollLeft, and ScrollRight methods that any discrete input source can call, including thumb swipe microgestures, keyboard input, and on-screen buttons.
Each DiscreteScrollInputProvider is bound to one interactor through its Interactor field, so scrolling is per-interactor rather than scene-wide. The component tracks the ScrollRect that its own interactor hovers, and applies scroll impulses to that panel. The interactor does not have to be a GazeInteractor: the field accepts any component that implements IInteractorView. Because the binding is one-to-one, a scroller stops applying scroll while its interactor is disabled, so a scroller bound to a hand interactor goes quiet while that hand is driving locomotion or holding a grabbed object. To support scrolling from more than one interactor, add one scroller to each. To follow whichever interactor is currently winning instead, assign an InteractorGroup to the Interactor field. InteractorGroup implements IInteractorView, so a single scroller then scrolls whatever the group’s active interactor hovers.
The MicrogestureScroll prefab packages the component together with the microgesture wiring, which is the setup this guide covers.
Diagram of the microgesture scroll architecture. On the gesture input path, OVRHand feeds OVRMicrogestureEventSource, which reports a thumb swipe to MicroGestureUnityEventWrapper. On the hover targeting path, a PointableCanvas and an interactor feed the PointableCanvasModule on the EventSystem. Both paths meet at DiscreteScrollInputProvider, which applies a scroll impulse to the hovered ScrollRect.

Prerequisites

  • Gaze interactions configured in your scene following Getting Started with Interaction SDK
  • An ISDK interaction rig containing at least one GazeInteractor
  • Meta XR Core SDK (com.meta.xr.sdk.core) installed, which provides OVRMicrogestureEventSource and OVRHand. This is included as a dependency of the Interaction SDK OVR integration package.
  • One or more Unity UI ScrollRect panels in the scene
  • Each Canvas set to World Space render mode with a PointableCanvas component, and a PointableCanvasModule on the scene’s EventSystem

Add a scroller to each interactor

  1. In the Project panel, search for MicrogestureScroll and select the MicrogestureScroll prefab, located in Packages > Meta XR Interaction SDK > Runtime > Prefabs > Microgestures.
    The Project panel browsed to the Microgestures prefab folder with the MicrogestureScroll prefab selected.
  2. Drag the prefab directly onto the GazeInteractor GameObject in the Hierarchy so that it becomes a child of that interactor. Dropping it onto the interactor is what lets the editor bind the two together, as described in the next section.
    Hierarchy panel showing the MicrogestureScroll GameObject parented under HandGazeInteractor.
  3. Repeat for every interactor that needs to support scrolling.
The prefab is a single GameObject carrying three components:
  • DiscreteScrollInputProvider: applies scroll impulses to the hovered ScrollRect.
  • OVRMicrogestureEventSource: reports thumb swipe microgestures for one hand.
  • Micro Gesture Unity Event Wrapper: routes each recognized gesture to a scroll method.
The MicrogestureScroll prefab in the Inspector, showing the Discrete Scroll Input Provider, OVR Microgesture Event Source, and Micro Gesture Unity Event Wrapper components.

Verify the interactor assignment

Select the MicrogestureScroll GameObject and check the Interactor field on the DiscreteScrollInputProvider component in the Inspector. It should name the interactor you dropped the prefab onto.
The Discrete Scroll Input Provider component in the Inspector with the Interactor field set to HandGazeInteractor (Gaze Interactor).
When the prefab is added to a scene, the editor fills this field by walking up the parent chain for a component that implements IInteractorView and assigning the first one it finds. Two limits apply:
  • The prefab asset ships with Interactor empty, and the search runs only at the moment the prefab is added to the scene. If you drop the prefab somewhere else and reparent it afterward, the field stays empty.
  • The search covers ancestors only. A scroller placed as a sibling of the interactor does not bind to it.
If the field is empty, assign the interactor by dragging it into the field. The Console reports Auto-wiring failed when no interactor is found in the parent chain, and an unassigned Interactor raises an assertion failure when you enter Play mode.

Assign the hand

The prefab ships with the OVRMicrogestureEventSourceHand field unset.
  1. Select the MicrogestureScroll GameObject.
  2. In the Inspector, locate the OVRMicrogestureEventSource component and assign the OVRHand for the hand that drives scrolling for this interactor.
    The OVR Microgesture Event Source component in the Inspector with the Hand field set to OVRHandDataSourceLeft (OVR Hand).
Each prefab instance carries one OVRMicrogestureEventSource and therefore listens to one hand. To accept swipes from both hands on the same interactor, add a second MicrogestureScroll under that interactor and assign the other OVRHand.
Leaving Hand unset raises a null reference error every frame, because the component reads the hand’s gesture state in Update.

Choose which directions scroll

Direction mapping lives on the Micro Gesture Unity Event Wrapper component, which exposes one UnityEvent per recognized gesture. Select the MicrogestureScroll GameObject to configure them.
Inspector eventGestureMethod called by default
When Swipe Up
Thumb swipe forward
ScrollUp
When Swipe Down
Thumb swipe backward
ScrollDown
When Swipe Left
Thumb swipe left
ScrollLeft
When Swipe Right
Thumb swipe right
ScrollRight
When Tap Center
Thumb tap
None
Each of the four swipe events holds a single entry targeting the DiscreteScrollInputProvider on the same GameObject.
The Micro Gesture Unity Event Wrapper component in the Inspector, with the When Swipe Up, When Swipe Down, When Swipe Left, and When Swipe Right events each bound to the matching DiscreteScrollInputProvider method.
  • To remap a direction, change the method in that entry’s function dropdown. To invert the vertical axis, set When Swipe Up to ScrollDown and When Swipe Down to ScrollUp.
  • To disallow a direction, select its entry and remove it with the − button. A swipe in that direction then does nothing.
ScrollUp moves the content up, and the other three methods follow the same convention.

Tune scroll behavior

Select the MicrogestureScroll GameObject and adjust the following properties on the DiscreteScrollInputProvider component.
PropertyDefaultDescription
Scroll Speed
2
The speed at which scrolling occurs. Multiplies viewport size to determine velocity. The field accepts any float value and enforces no range.
Stop Momentum On Target Change
Cleared
When set, scrolling stops as soon as the interactor’s target changes.
The Discrete Scroll Input Provider component in the Inspector, showing the Scroll Speed property under Scroll Settings and Stop Momentum On Target Change under Behavior.
Two behaviors are fixed and are not exposed as properties:
  • Repeated swipes in the same direction accumulate velocity, so the panel scrolls faster. A swipe in the opposite direction stops the current motion before scrolling the new way.
  • When the hovered ScrollRect does not support the swiped axis, the component walks up the hierarchy and scrolls the first ancestor ScrollRect that does. This is what makes a vertical swipe over a horizontal-only child scroll its vertical parent.
DiscreteScrollInputProvider offers no per-ScrollRect overrides. Tune each panel on its own Scroll Rect component instead. Clear Horizontal or Vertical to restrict the axes, set Movement Type to Elastic and adjust Elasticity to change the bounce at the ends, and use Inertia with Deceleration Rate to change how quickly the panel coasts to a stop. See Unity Canvas Integration for how ISDK pointers drive Unity UI.

Migrate from MicrogestureScrollProvider

Earlier releases used one scene-wide MicrogestureScrollProvider, paired with a MicrogestureScrollSettings component for per-panel overrides. Both are deprecated and neither drives scrolling any more.
  1. Delete the MicrogestureScrollProvider GameObject from your scene.
  2. Remove every MicrogestureScrollSettings component from your ScrollRect panels. DiscreteScrollInputProvider does not read them, so the strength overrides and axis gating they declare have no effect.
  3. Recreate per-panel behavior on the Scroll Rect component itself. It already exposes Horizontal and Vertical for axis gating, Movement Type with Elasticity, and Inertia with Deceleration Rate.
  4. Add a MicrogestureScroll prefab under each interactor that needs scrolling, following the sections above.
The old provider’s scene-wide Invert Vertical and Invert Horizontal toggles have no replacement property. Invert an axis by remapping the swipe events, as described in Choose which directions scroll.

Troubleshooting

Nothing scrolls when you swipe

Symptom: You swipe while looking at a ScrollRect panel and nothing moves.
Solution: Check each of the following:
  • The Interactor field on DiscreteScrollInputProvider names the interactor doing the hovering.
  • The Hand field on OVRMicrogestureEventSource names the OVRHand you are swiping with.
  • The Canvas holding the ScrollRect uses World Space render mode and has a PointableCanvas component, and the scene’s EventSystem has a PointableCanvasModule.
  • The ScrollRect content is larger than its viewport. Content that fits has nothing to scroll.
  • The swiped axis is enabled on the Scroll Rect component, on the panel or on one of its ancestors.

Scrolling stops while the hand is doing something else

Symptom: Scrolling works until you grab an object or start moving, then stops until you release.
Solution: This is expected. A scroller applies scroll only while its bound interactor is active, so a scroller bound to an interactor that gets disabled during locomotion or grabbing goes inactive with it. To keep scrolling available in those states, bind a scroller to an interactor that stays active, such as a GazeInteractor.

Only one interactor can scroll

Symptom: Scrolling works from one interactor and does nothing from another.
Solution: Each DiscreteScrollInputProvider serves exactly one interactor. Add a MicrogestureScroll prefab under each interactor that needs to scroll.

Learn more