Skip to main content
Version: 14 Oct 2024

Input Device Feature Values

It is recommended that developers read the controller input using Unity's Input System. However, developers can obtain the controller's input directly from the InputDevice. This section provides an example of reading input using the TryGetFeatureValue method and XRCommonUsages features.

caution

This feature requires the HAND_TRACKING permission to be enabled in your project's Permissions Settings (Edit > Project Settings > Magic Leap > Permissions).

Example

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


using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.XR;
using InputDevice = UnityEngine.XR.InputDevice;
using XRCommonUsages = UnityEngine.XR.CommonUsages;

/// <summary>
/// This script finds a connected controller and logs the input values using the TryGetFeatureValue method and XRCommonUsages.
/// </summary>
public class ControllerInputExample : MonoBehaviour
{
private readonly StringBuilder _stringBuilder = new StringBuilder();
private InputDevice _trackedDevice;

private void Update()
{
if (GetControllerDevice(ref _trackedDevice))
{
_stringBuilder.Clear();

if (_trackedDevice.TryGetFeatureValue(XRCommonUsages.devicePosition, out Vector3 devicePosition))
_stringBuilder.AppendLine($"Device Position: {devicePosition}");

if (_trackedDevice.TryGetFeatureValue(XRCommonUsages.deviceRotation, out Quaternion deviceRotation))
_stringBuilder.AppendLine($"Device Rotation: {deviceRotation}");

if (_trackedDevice.TryGetFeatureValue(XRCommonUsages.deviceVelocity, out Vector3 deviceVelocity))
_stringBuilder.AppendLine($"Velocity: {deviceVelocity}");

if (_trackedDevice.TryGetFeatureValue(XRCommonUsages.deviceAngularVelocity, out Vector3 deviceAngularVelocity))
_stringBuilder.AppendLine($"Angular Velocity: {deviceAngularVelocity}");

if (_trackedDevice.TryGetFeatureValue(XRCommonUsages.trigger, out float deviceTriggerValue))
_stringBuilder.AppendLine($"Trigger Value: {deviceTriggerValue}");

if (_trackedDevice.TryGetFeatureValue(XRCommonUsages.gripButton, out bool deviceIsBumperDown))
_stringBuilder.AppendLine($"IsBumperDown: {deviceIsBumperDown}");

if (_trackedDevice.TryGetFeatureValue(XRCommonUsages.menuButton, out bool deviceIsMenuDown))
_stringBuilder.AppendLine($"IsMenuDown: {deviceIsMenuDown}");

if (_trackedDevice.TryGetFeatureValue(XRCommonUsages.primary2DAxisTouch, out bool deviceIsTouchActive))
_stringBuilder.AppendLine($"IsTouchActive: {deviceIsTouchActive}");

if (_trackedDevice.TryGetFeatureValue(XRCommonUsages.primary2DAxis, out Vector2 deviceTouchPos))
_stringBuilder.AppendLine($"TouchPos: {deviceTouchPos}");

//Log the controllers feature values
Debug.Log(_stringBuilder);
}
}

// Checks to see if the referenced Input Device is a tracked Controller.
private bool GetControllerDevice(ref InputDevice controller)
{
if(IsTrackedController(controller)){
return true;
}

// If we do not have reference to a valid input device or if it is not being tracked search for a new one.
List<InputDevice> devices = new List<InputDevice>();
InputDevices.GetDevicesWithCharacteristics(
InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.HeldInHand, devices);

for (int i = 0; i < devices.Count; i++)
{
if (IsTrackedController(devices[i]))
{
Debug.Log($"device {i}: {devices[i].characteristics} [isTracked: {tracked}]");
controller = devices[i];
return true;
}
}
return false;
}

// Check to see if the controller is valid and tracked.
private bool IsTrackedController(InputDevice controller)
{
// If we have a reference to an input device, make sure that it is tracked.
if (controller.isValid)
{
controller.TryGetFeatureValue(XRCommonUsages.isTracked, out bool tracked);
if (tracked)
{
// If the device is not tracked, search for a new input device.
return true;
}
}
return false;
}
}