Develop

Create a Gaze-Grabbable Object

Updated: Sep 8, 2026

Overview

Gaze grab lets the user pick up an object by looking at it and pinching, without requiring the hand to be near the object. The setup reuses the same UIsdkGrabbableComponent as the standard grab flow, with two extra properties to configure. For the underlying concepts, see Gaze Grab Interactions.

Prerequisites

  • A pawn with the gaze rig configured. See Getting Started with Gaze Interactions.
  • The Epic OpenXR plugin is enabled, and Project Settings > Plugins > Meta XR > General > XR API is set to Epic Native OpenXR.
  • A working grab setup on hands or controllers. See Grab Interactions.
  • A target actor with a Static Mesh (or another component you intend to use as the grab collider).

Add the Grabbable Component

Add UIsdkGrabbableComponent (display name ISDK Grabbable Component) to the actor you want the user to gaze-grab. The component is marked BlueprintSpawnableComponent, so it appears in the Add Component menu of any Blueprint actor and can be added at runtime.
Components panel of a grabbable doll actor with the grabbable component attached.
The rest of the setup, including selecting between one-hand and two-hand transformers and configuring the input method, is identical to the hand-grab flow. See Grab Interactions for the full setup.

Enable Ray Grab in Allowed Grab Detector Types

In the Details panel, find Allowed Grab Detector Types and check Ray Grab. This property is a bitmask over EIsdkGrabDetectorType, and its default value is Hand Grab only. Without this change, gaze grab silently fails on this object.
Allowed Grab Detector Types dropdown with Hand Grab and Ray Grab checked.
Gaze does not have its own detector slot on the grabber. The gaze rig injects a UIsdkSimpleGrabDetector into the ray-grab slot on each grabber when gaze is active. That detector gates every candidate on IsRayGrabAllowed(), so a grabbable that permits only Hand Grab is filtered out before it can ever be selected by gaze.
To keep near-hand grab working alongside gaze on the same object, leave Hand Grab checked in addition to Ray Grab.
Flow from the gaze rig through the visibility trace to the ray grab allowance check.
The gaze rig injects a detector into the ray-grab slot, so a grabbable that allows only HandGrab is filtered out.

Set the Gaze Policy

The GazePolicy property controls whether this grabbable participates in gaze grab. The default is UsePluginSetting.
Details panel with Gaze Policy set to Allow in the Gaze category.
ValueDisplay NameEffect
UsePluginSetting
Use Plugin Setting
Defers to the plugin’s Allow Gaze By Default setting
Allow
Allow
Opts this grabbable in regardless of the plugin default
Disallow
Disallow
Excludes this grabbable regardless of the plugin default
Use Allow when the project-level default is Disallow, or when the object needs a per-object opt-in that is independent of the plugin default.

Configure the Grab Collider

The ColliderMode property selects which component acts as the grab collider. The default value is FindStaticMesh, which resolves to the actor’s Static Mesh Component. Other supported values are FindByName, Sphere, Box, and CustomMesh, for actors that have multiple meshes or use a custom collider shape.
Details panel with Collider Mode set to Find Static Mesh.
The collider you choose must set its collision response to Block on the channel used by UIsdkGazeTargetingComponent::GazeCollisionChannel, which defaults to ECC_Visibility (Visibility). If the collider is set to Overlap or Ignore on that channel, the gaze trace produces no hit and the object never becomes hoverable.
Collision presets with the Visibility trace response set to Block.
Grabbable resolution runs UIsdkFunctionLibrary::FindGrabbableByComponent(Hit.GetComponent()) against the hit component itself, not the hit actor. A widget surface or decorative mesh in front of the grab collider intercepts the hover before it reaches the grabbable.

Verify in Play in Editor

Bind to OnGazeGrabbableChanged on the gaze targeting component to log every hover transition, including the transition back to nullptr when the gaze leaves a grabbable.
// In your actor header
UFUNCTION()
void HandleGazeGrabbableChanged(UIsdkGrabbableComponent* NewGrabbable);

// In BeginPlay
if (UIsdkGazeRigComponent* GazeRig = FindComponentByClass<UIsdkGazeRigComponent>())
{
    if (UIsdkGazeTargetingComponent* Targeting = GazeRig->GetGazeTargeting())
    {
        Targeting->OnGazeGrabbableChanged.AddDynamic(
            this, &AMyActor::HandleGazeGrabbableChanged);
    }
}
The delegate fires on every transition: with a non-null grabbable when the gaze ray first resolves to a valid target, and with nullptr when the ray moves off a previously hovered grabbable. If you never see a fire while looking directly at the object, the trace is not producing a mappable hit; if you see the object enter and then immediately leave on every glance, the hit is landing on a non-grabbable component in front of it. Enter Play in Editor, look at the object, and pinch. If nothing happens, use the table below to narrow the cause.
Play in Editor scene with a gaze hover tooltip on an object and a gaze state readout.
SymptomCause
No gaze hover on the object
The grab collider does not Block the Visibility channel, another collider or widget is intercepting the hit, or the gaze rig is missing from the pawn
Gaze hovers the object but pinch does nothing
Allowed Grab Detector Types is missing Ray Grab, the grabbable and grabber disagree on input method (Pinch vs Palm), or the object is already held

Learn more

Now that you know how to make an object gaze-grabbable, continue on to the following guides: