Skip to main content
Version: 20 Mar 2024

Input Device Feature Values

It is recommended that developers use the Unity Input System to obtain the Gaze Input. However, developers can also obtain eye tracking input directly from the InputDevice. This section provides an example of how to read input using the TryGetFeatureValue method and EyeTrackingUsages features.

caution

This features requires the EYE_TRACKING permission to be requested at runtime and enabled in your project's Manifest Settings (Edit > Project Settings > Magic Leap > Manifest Settings).

caution

This feature requires the Eye Gaze Interaction Profile OpenXR Interaction Profile to be enabled in your project's OpenXR Settings (Window > XR Plugin Manager > OpenXR Settings).

note

If your Application collects, stores, transfers or otherwise uses data off the Magic Leap 2 device that is received via this API, then you must comply with the Magic Leap 2 Eye Tracking Data Transparency Policy.

Example

This example script finds a connected controller if one is present and logs the input values using the TryGetFeatureValue() method and EyeTrackingUsages.

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.MagicLeap;
using UnityEngine.XR.OpenXR.Features.Interactions;
using InputDevice = UnityEngine.XR.InputDevice;

/// <summary>
/// This script finds a connected eye tracking input device and logs it's input values.
/// Requires the Eye Gaze Interaction Profile to be enabled in the project's OpenXR settings
/// </summary>
public class GazeInputExample : MonoBehaviour
{
private InputDevice _eyeTrackingDevice;
private bool _permissionGranted;
private readonly MLPermissions.Callbacks _permissionCallbacks = new MLPermissions.Callbacks();

void Start()
{
// Request Magic Leap Eye Tracking Permission
_permissionCallbacks.OnPermissionGranted += OnPermissionGranted;
_permissionCallbacks.OnPermissionDenied += OnPermissionDenied;
_permissionCallbacks.OnPermissionDeniedAndDontAskAgain += OnPermissionDenied;
MLPermissions.RequestPermission(MLPermission.EyeTracking, _permissionCallbacks);
}

private void Update()
{
if (!_permissionGranted)
{
// Wait for permission
return;
}

// Get the EyeTracking Input Device
if (!_eyeTrackingDevice.isValid)
{
List<InputDevice> inputDeviceList = new List<InputDevice>();
InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.EyeTracking, inputDeviceList);
if (inputDeviceList.Count > 0)
{
_eyeTrackingDevice = inputDeviceList[0];
}

if (!_eyeTrackingDevice.isValid)
{
Debug.LogWarning($"Unable to acquire eye tracking device. Have permissions been granted?");
return;
}
}

//Obtain gaze tracking input
bool hasData = _eyeTrackingDevice.TryGetFeatureValue(CommonUsages.isTracked, out bool isTracked);
hasData &= _eyeTrackingDevice.TryGetFeatureValue(EyeTrackingUsages.gazePosition, out Vector3 position);
hasData &= _eyeTrackingDevice.TryGetFeatureValue(EyeTrackingUsages.gazeRotation, out Quaternion rotation);

if (isTracked && hasData)
{
Vector3 direction = rotation * Vector3.forward;
// Use the position and rotation
Debug.Log($"Gaze Origin: {position} | Gaze Rotation: {rotation} | Gaze Direction {direction}");
}
}

private void OnDestroy()
{
_permissionCallbacks.OnPermissionGranted -= OnPermissionGranted;
_permissionCallbacks.OnPermissionDenied -= OnPermissionDenied;
_permissionCallbacks.OnPermissionDeniedAndDontAskAgain -= OnPermissionDenied;
}

private void OnPermissionDenied(string permission)
{
// Logic for permission not granted
Debug.LogError($"Eye tracking permission denied.");
}

private void OnPermissionGranted(string permission)
{
_permissionGranted = true;
}
}