Skip to main content
Version: 20 Mar 2024

Inputs Sample

This section describes how to read Magic Leap 2's controller input using Unity's Input System and Input Actions. The samples in this category assume that you are using the MagicLeapOpenXRInput.inputactions asset provided in the Magic Leap Samples. However, they can be easily modified to support custom input actions.

Import Magic Leap Rig & OpenXR Input Samples


  • Magic Leap Unity SDK Installed

Importing the Magic Leap Rig & OpenXR Input Samples

  1. Opening Unity Package Manager
    1. Navigate to Window > Package Manager in Unity. This will open the Package Manager window.
  2. Selecting the Package
    1. In the Package Manager, select the Magic Leap SDK package from the list.
  3. Importing Samples
    1. In the package details, locate the Samples section which lists available samples.
    2. Click on the Import button next to the ML Rig & OpenXR Input sample.
  4. Confirming Import
    1. If prompted, confirm the import action by clicking Import.
    2. Unity will import the selected sample into your project. This may take a moment.
  5. Accessing Imported Samples
    1. Locate Magic Leap Rig and Input assets inside your project's /Assets/Samples/MagicLeapSDK/<Version>/ directory.
The Magic Leap SDK Package with the "ML Rig & OpenXR Input" sample selected.

Generate C# Classes from Input Actions

Once the input Samples have been imported, you can obtain input from the Magic Leap 2 using Unity Input System. One of the fastest ways to get started is to auto-generate the code required to access Magic Leap Input and it's bindings in of your scripts.

  1. In the Project window, navigate to the Assets/Samples/Magic Leap SDK/<Version>/ML Rig & OpenXR Input/ directory.
  2. Select the MagicLeapOpenXRInput asset to view it's properties in the Inspector.
  3. In the Inspector, select Generate C# Class
  4. Click Apply.
The MagicLeapOpenXRInput asset selected in the Project Folder with the "Generate C# Class" option highlighted.

Using the Input Script

This section demonstrates how to use Unity's Input System to access input from the Magic Leap 2 controller using the script generated from the Magic Leap Samples. Developers can read the data directly or subscribing to an InputAction callback.

Input actions contain 3 callbacks, started, performed, and canceled. While the order and how the events are triggered depend on the type of the action, the table below shows the default behavior.

InputAction.startedWhen a control is actuated (i.e. moving away from its resting position)
InputAction.performedCalled right after started, and continues to be called while the action is being performed.
InputAction.canceledWhen the control moves back to its default value (i.e. resting position)


The example script below subscribes to the Magic Leap controller's input events, and debugs the input values to the Debug Log.


This example assumes that the MagicLeapOpenXRInput script was generated using the default settings from the MagicLeapOpenXRInput.inputactions asset. If you changed the input action bindings or if you changed the namespace and name of the generated script, you will need to adjust the code below accordingly.

using UnityEngine;
using UnityEngine.InputSystem;

public class ExampleClass : MonoBehaviour
// This is was autogenerated and allows developers to create a dynamic
// instance of an InputActionAsset which includes predefined action maps
// that correspond to all of the Magic Leap 2's input.
private MagicLeapOpenXRInput _magicLeapInputs;

// This class is an Action Map and was autogenerated by the Unity Input
// System and includes predefined bindings for the Magic Leap 2 Controller
// Input Events.
private MagicLeapOpenXRInput.ControllerAction _controllerActions;

void Start()
// Initialize the InputActionAsset
_magicLeapInputs = new MagicLeapOpenXRInput();

//Initialize the ControllerActions using the Magic Leap Input
_controllerActions = new MagicLeapOpenXRInput.ControllerActions(_magicLeapInputs);

//Subscribe to your choice of the controller events
_controllerActions.IsTracked.performed += IsTrackedOnPerformed;
_controllerActions.Trigger.performed += HandleOnTrigger;
_controllerActions.Bumper.performed += HandleOnBumper;

void Update()
//Only debug the values if the controller is connected.
//Read the input values directly
Debug.Log("Position:" + _controllerActions.Position.ReadValue<Vector3>());
Debug.Log("Rotation:" + _controllerActions.Rotation.ReadValue<Quaternion>());

// Handles the event to determine if the controller is tracking.
private void IsTrackedOnPerformed(InputAction.CallbackContext obj)
Debug.Log("The Controller Is tracking");

// Handles the event for the Trigger.
private void HandleOnTrigger(InputAction.CallbackContext obj)
float triggerValue = obj.ReadValue<float>();
Debug.Log("The Trigger value is : " + triggerValue);

// Handles the event for the Bumper.
private void HandleOnBumper(InputAction.CallbackContext obj)
bool bumperDown = obj.ReadValueAsButton();
Debug.Log("The Bumper is pressed down " + bumperDown);
Debug.Log("The Bumper was released this frame: " + obj.action.WasReleasedThisFrame());

// Handles the disposing all of the input events.
void OnDestroy()
_controllerActions.IsTracked.performed -= IsTrackedOnPerformed;
_controllerActions.Trigger.performed -= HandleOnTrigger;
_controllerActions.Bumper.performed -= HandleOnBumper;

See also