docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    XR Hand Device

    The XRHandSubsystem exposes the XRHandDevice input device within the Unity Input System, which is a type of TrackedDevice. This is automatically done when the subsystem is running, such as when enabling the Hand Tracking Subsystem OpenXR feature.

    Configuration

    The runtime value of XRHandSubsystem.handSubsystemConfiguration drastically alters the meaning of the <XRHandDevice> input device controls, essentially switching it between two entirely different input devices. You can set the configuration on the XRHandSubsystem to choose between the XRHandSubsystemConfiguration.xrHandDevicePoseSource options. Refer to Access hand data: Get the XRHandSubsystem instance to learn how to get the XRHandSubsystem to change the configuration.

    A simple way to change from the default Legacy mode to Common Gestures mode is to add the following component to a GameObject:

    using System;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.XR.Hands;
    using UnityEngine.XR.Hands.Configuration;
    
    /// <summary>
    /// A component that automatically sets the hand subsystem configuration
    /// to use the Common Gestures mode instead of Legacy.
    /// </summary>
    class UpdateHandsConfigurationSample : MonoBehaviour
    {
        List<XRHandSubsystem> m_HandSubsystems;
    
        void Start()
        {
            if (!TryGetHandSubsystem(out var handSubsystem))
            {
                Debug.LogWarning("Hand Tracking Subsystem not found or not running," +
                    " can't update its config.", this);
                return;
            }
    
            var config = handSubsystem.handSubsystemConfiguration;
            config.xrHandDevicePoseSource = XRHandDevicePoseSource.CommonGestures;
    
            handSubsystem.UpdateHandsConfiguration(config);
        }
    
        // Gets the first hand subsystem. If there are multiple,
        // returns the first running subsystem.
        bool TryGetHandSubsystem(out XRHandSubsystem handSubsystem)
        {
            m_HandSubsystems ??= new List<XRHandSubsystem>();
            SubsystemManager.GetSubsystems(m_HandSubsystems);
            if (m_HandSubsystems.Count == 0)
            {
                handSubsystem = default;
                return false;
            }
    
            if (m_HandSubsystems.Count > 1)
            {
                for (var i = 0; i < m_HandSubsystems.Count; ++i)
                {
                    handSubsystem = m_HandSubsystems[i];
                    if (handSubsystem.running)
                        return true;
                }
            }
    
            handSubsystem = m_HandSubsystems[0];
            return true;
        }
    }
    

    The Common Gestures mode is the recommended path to use for your OpenXR project. The Legacy mode is default to avoid breaking existing projects which already made use of the <XRHandDevice> and the locations of each of the poses, and for maximum compatibility in projects which are not targeting OpenXR which may not support common gestures.

    Note

    When using Common Gestures mode on OpenXR, you must also enable the Hand Interaction Profile. Refer to Common Gestures for more details.

    XRHandSubsystemProvider implementers

    For advanced users or for platform providers, the XRHandSubsystemDescriptor contains properties which indicate whether the provider can supply each of the Poses or Gesture values. The XRHandSubsystemProvider.canSurfaceCommonPoseData must also be implemented to indicate that the provider can supply data for populating XRCommonHandGestures.

    Available controls

    The following tables outline the mapping between the data sources and Unity's control paths on the input device, along with any applicable OpenXR path for each value.

    To specify a particular hand, you can add {LeftHand} or {RightHand} after the <XRHandDevice> in the binding, such as <XRHandDevice>{LeftHand}/devicePosition.

    Some controls defined in the <XRHandDevice> are not supplied a value depending on the configuration mode, as outlined in Configuration.

    Note

    The set of "device" pose bindings differs between configuration modes. Those four binding paths (devicePosition, deviceRotation, isTracked, and trackingState) will either map to the Wrist pose or the Grip pose.

    Legacy (Default)

    The following tables apply when the configuration mode is set to XRHandDevicePoseSource.LegacyJointRecognition:

    Poses

    These poses represent the joint poses from a hand, specifically XRHandJointID.Wrist, XRHandJointID.Palm, XRHandJointID.IndexTip, and XRHandJointID.ThumbTip. Refer to Joint nomenclature for a visual representation of each joint.

    You can bind to these poses with input actions to use in your components, such as Tracked Pose Driver, instead of querying them directly from an XRHand. Refer to Access hand data: Get joint data to learn how to get hand joint poses through scripting API instead.

    Data Binding Path Type
    Wrist Position <XRHandDevice>/wristPosition
    <XRHandDevice>/devicePosition
    (or <TrackedDevice>/devicePosition)
    Vector3
    Wrist Rotation <XRHandDevice>/wristRotation
    <XRHandDevice>/deviceRotation
    (or <TrackedDevice>/deviceRotation)
    Quaternion
    Wrist Is Tracked <XRHandDevice>/wristIsTracked
    <XRHandDevice>/isTracked
    (or <TrackedDevice>/isTracked)
    Boolean
    Wrist Tracking State <XRHandDevice>/wristTrackingState
    <XRHandDevice>/trackingState
    (or <TrackedDevice>/trackingState)
    Integer (flags enum)
    Palm Position <XRHandDevice>/gripPosition Vector3
    Palm Rotation <XRHandDevice>/gripRotation Quaternion
    Palm Is Tracked <XRHandDevice>/gripIsTracked Boolean
    Palm Tracking State <XRHandDevice>/gripTrackingState Integer (flags enum)
    Index Tip Position <XRHandDevice>/pokePosition Vector3
    Index Tip Rotation <XRHandDevice>/pokeRotation Quaternion
    Index Tip Is Tracked <XRHandDevice>/pokeIsTracked Boolean
    Index Tip Tracking State <XRHandDevice>/pokeTrackingState Integer (flags enum)
    Thumb Tip Position <XRHandDevice>/pinchPosition Vector3
    Thumb Tip Rotation <XRHandDevice>/pinchRotation Quaternion
    Thumb Tip Is Tracked <XRHandDevice>/pinchIsTracked Boolean
    Thumb Tip Tracking State <XRHandDevice>/pinchTrackingState Integer (flags enum)
    Note

    Legacy mode does not supply an Aim Pose. Those four binding paths (aimPosition, aimRotation, aimIsTracked, and aimTrackingState) will always remain default values.

    Note

    Legacy mode does not supply any gesture values. Those nine binding paths (graspValue, graspFirm, etc.) will always remain default values.

    Common Gestures

    For this input device to work on OpenXR, you must also enable the Hand Tracking Subsystem OpenXR feature and enable the Hand Interaction Profile within the Edit > Project Settings > XR Plug-in Management > OpenXR window. The OpenXR Plugin package must be at version 1.8.1 or newer. You must also enable this mode in the XRHandSubsystem configuration, as outlined in Configuration.

    The following tables apply when the configuration mode is set to XRHandDevicePoseSource.CommonGestures:

    Poses

    These poses represent the poses from a hand interaction profile, specifically Grip pose, Poke pose, Pinch pose, and Aim pose, and the wrist joint pose.

    You can bind to these poses with input actions to use in your components like Tracked Pose Driver instead of the HandInteraction poses to support hand playback overriding the values or for supporting simulation.

    Data Binding Path(s) Type OpenXR Path
    Wrist Position <XRHandDevice>/wristPosition Vector3 XR_HAND_JOINT_WRIST_EXT
    Wrist Rotation <XRHandDevice>/wristRotation Quaternion XR_HAND_JOINT_WRIST_EXT
    Wrist Is Tracked <XRHandDevice>/wristIsTracked Boolean XR_HAND_JOINT_WRIST_EXT
    Wrist Tracking State <XRHandDevice>/wristTrackingState Integer (flags enum) XR_HAND_JOINT_WRIST_EXT
    Grip Position <XRHandDevice>/gripPosition
    <XRHandDevice>/devicePosition
    (or <TrackedDevice>/devicePosition)
    Vector3 /input/grip/pose
    Grip Rotation <XRHandDevice>/gripRotation
    <XRHandDevice>/deviceRotation
    (or <TrackedDevice>/deviceRotation)
    Quaternion /input/grip/pose
    Grip Is Tracked <XRHandDevice>/gripIsTracked
    <XRHandDevice>/isTracked
    (or <TrackedDevice>/isTracked)
    Boolean /input/grip/pose
    Grip Tracking State <XRHandDevice>/gripTrackingState
    <XRHandDevice>/trackingState
    (or <TrackedDevice>/trackingState)
    Integer (flags enum) /input/grip/pose
    Poke Position <XRHandDevice>/pokePosition Vector3 /input/poke_ext/pose
    Poke Rotation <XRHandDevice>/pokeRotation Quaternion /input/poke_ext/pose
    Poke Is Tracked <XRHandDevice>/pokeIsTracked Boolean /input/poke_ext/pose
    Poke Tracking State <XRHandDevice>/pokeTrackingState Integer (flags enum) /input/poke_ext/pose
    Pinch Position <XRHandDevice>/pinchPosition Vector3 /input/pinch_ext/pose
    Pinch Rotation <XRHandDevice>/pinchRotation Quaternion /input/pinch_ext/pose
    Pinch Is Tracked <XRHandDevice>/pinchIsTracked Boolean /input/pinch_ext/pose
    Pinch Tracking State <XRHandDevice>/pinchTrackingState Integer (flags enum) /input/pinch_ext/pose
    Aim Position <XRHandDevice>/aimPosition Vector3 /input/aim/pose
    Aim Rotation <XRHandDevice>/aimRotation Quaternion /input/aim/pose
    Aim Is Tracked <XRHandDevice>/aimIsTracked Boolean /input/aim/pose
    Aim Tracking State <XRHandDevice>/aimTrackingState Integer (flags enum) /input/aim/pose

    Gesture values

    These values represent three groups of action inputs from a hand interaction profile, specifically Grasp action, Pinch action, and Aim activate action.

    Data Binding Path Type OpenXR Path
    The extent to which a user is making a fist <XRHandDevice>/graspValue Float
    0 to 1
    /input/grasp_ext/value
    Is the user making a fist <XRHandDevice>/graspFirm Boolean /input/grasp_ext/value
    Precondition to making a fist <XRHandDevice>/graspReady Boolean /input/grasp_ext/ready_ext
    The extent to which a user is pinching <XRHandDevice>/pinchValue Float
    0 to 1
    /input/pinch_ext/value
    Is the user pinching <XRHandDevice>/pinchTouched Boolean /input/pinch_ext/value
    Precondition to making a pinch <XRHandDevice>/pinchReady Boolean /input/pinch_ext/ready_ext
    The extent to which a user is aim pinching <XRHandDevice>/aimActivateValue Float
    0 to 1
    /input/aim_activate_ext/value
    Is the user aim pinching <XRHandDevice>/aimActivated Boolean /input/aim_activate_ext/value
    Precondition to making an aim pinch <XRHandDevice>/aimActivateReady Boolean /input/aim_activate_ext/ready_ext
    Note

    These values are not available when using Legacy mode. Those nine binding paths (graspValue, graspFirm, etc.) will always remain default values.

    Additional resources

    • Meta Hand Tracking Aim OpenXR feature
    • OpenXR Hand Interaction Profile
    In This Article
    Back to top
    Copyright © 2026 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)