# Controller Position only works in right hand

**URL:** <https://forum.magicleap.cloud/t/controller-position-only-works-in-right-hand/6097>\
**Category:** Unity Development\
**Created:** [July 23, 2025, 7:29am UTC](https://forum.magicleap.cloud/t/controller-position-only-works-in-right-hand/6097 "2025-07-23T07:29:28Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ArDevKarl](https://avatars.discourse-cdn.com/v4/letter/a/7ea924/32.png) [@ArDevKarl](https://forum.magicleap.cloud/u/ArDevKarl)\
**Post date:** [July 23, 2025, 7:29am UTC](https://forum.magicleap.cloud/t/controller-position-only-works-in-right-hand/6097/1 "2025-07-23T07:29:29Z")

</div>

The following code is used to wrap the ML2-Controller inputs. This only works, when the user is holding the controller in the right hand. I need this to work always, no matter where the contoller is tracked or held. Is there a parameter to be set somwhere, to ignore the handedness?

```auto
using Core.Singletons;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;

namespace Qvra.UI
{
    public class LeapControllerInputHandler : Singleton<LeapControllerInputHandler>
    {
        public UnityEvent<Vector2> OnTouchpadUsed = new();
        public UnityEvent<float> OnTriggerUsed = new();
        public UnityEvent<float> OnTouchpadForce = new();
        public UnityEvent OnBumperPressed = new();
        public UnityEvent OnTouchpadClicked = new();
        public UnityEvent OnMenuPressed = new();
        public ControllerPresenceChecker PresenceChecker { get; private set; }

        public LeapControllerInputHandler()
        {
            PresenceChecker = new();
            PresenceChecker.Enable();
            _magicLeapInputs = new();
            _magicLeapInputs.Enable();
            _controllerActions = new MagicLeapInputs.ControllerActions(_magicLeapInputs);

            _controllerActions.Trigger.performed += TriggerPressed;
            _controllerActions.Bumper.performed += BumperPressed;
            _controllerActions.Menu.performed += MenuPressed;
            _controllerActions.TouchpadTouch.performed += TouchpadClicked;
            _controllerActions.TouchpadPosition.performed += TouchPadPosition;
            _controllerActions.TouchpadForce.performed += TouchpadForce;
        }

        public Vector3 ControllerPosition() => _controllerActions.Position.ReadValue<Vector3>();

        public Quaternion ControllerRotation() => _controllerActions.Rotation.ReadValue<Quaternion>();

        private void TouchpadForce(InputAction.CallbackContext context)
        {
            var value = context.ReadValue<float>();
            OnTouchpadForce.Invoke(value);
        }

        private void TouchPadPosition(InputAction.CallbackContext context)
        {
            var value = context.ReadValue<Vector2>();
            OnTouchpadUsed.Invoke(value);
        }

        private void TriggerPressed(InputAction.CallbackContext context)
        {
            var value = context.ReadValue<float>();
            OnTriggerUsed.Invoke(value);
        }

        private void BumperPressed(InputAction.CallbackContext context)
        {
            OnBumperPressed.Invoke();
        }

        private void MenuPressed(InputAction.CallbackContext context)
        {
            OnMenuPressed.Invoke();
        }

        private void TouchpadClicked(InputAction.CallbackContext context)
        {
            OnTouchpadClicked.Invoke();
        }

        public void OnDestroy()
        {
            _controllerActions.Trigger.performed -= TriggerPressed;
            _controllerActions.Bumper.performed -= BumperPressed;
            _controllerActions.Menu.performed -= MenuPressed;
            _controllerActions.TouchpadTouch.performed -= TouchpadClicked;
            _controllerActions.TouchpadPosition.performed -= TouchPadPosition;
            _controllerActions.TouchpadForce.performed -= TouchpadForce;

            _magicLeapInputs.Dispose();
        }

        private MagicLeapInputs _magicLeapInputs;
        private MagicLeapInputs.ControllerActions _controllerActions;

    }
}

```

Hand related subsystems:

 ![image](https://us1.discourse-cdn.com/flex019/uploads/magicleap1/original/2X/d/d3323f5645dd65c5cbdec34175cfb41786abdbe9.png)

**Unity Editor version** : 6000.0.44f1  
**ML2 OS version** : 1.12  
**Leap SDK version** : 2.5.0

---

<div class="post-metadata">

**Author:** ![magicbot](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.magicleap.cloud/magicbot/32/2470_2.png) [@magicbot](https://forum.magicleap.cloud/u/magicbot)\
**Post date:** [July 23, 2025, 8:35pm UTC](https://forum.magicleap.cloud/t/controller-position-only-works-in-right-hand/6097/2 "2025-07-23T20:35:33Z")

</div>

I recommend using the the OpenXR version of the MRTK 3 package

You can compare your results to our example project project. There fully configured branches of the MRTK3’s MRTKDevTemplate project available on Magic Leap’s github fork of the project to run on ML2.

Here is the branch for Unity 6 and OpenXR

> **[GitHub - magicleap/MixedRealityToolkit-Unity at mrtk3\_Unity6\_MagicLeap2\_OpenXR](https://github.com/magicleap/MixedRealityToolkit-Unity/tree/mrtk3_Unity6_MagicLeap2_OpenXR)**
>
> mrtk3\_Unity6\_MagicLeap2\_OpenXR

---

<div class="post-metadata">

**Author:** ![ArDevKarl](https://avatars.discourse-cdn.com/v4/letter/a/7ea924/32.png) [@ArDevKarl](https://forum.magicleap.cloud/u/ArDevKarl)\
**Post date:** [July 24, 2025, 6:02am UTC](https://forum.magicleap.cloud/t/controller-position-only-works-in-right-hand/6097/3 "2025-07-24T06:02:35Z")

</div>

The DevTemplate contains Magic Leap SDK 2.6.0. The official GitHub page has only version 2.3.0 flagged as latest: [Releases · magicleap/MagicLeapUnitySDK · GitHub](https://github.com/magicleap/MagicLeapUnitySDK/releases)

How do I get 2.6.0 into my project the official way? I cannot update the SDK via PackageManger

---

<div class="post-metadata">

**Author:** ![ArDevKarl](https://avatars.discourse-cdn.com/v4/letter/a/7ea924/32.png) [@ArDevKarl](https://forum.magicleap.cloud/u/ArDevKarl)\
**Post date:** [July 24, 2025, 8:23am UTC](https://forum.magicleap.cloud/t/controller-position-only-works-in-right-hand/6097/4 "2025-07-24T08:23:13Z")

</div>

Update: I found out, that the problem actually only applies to the inputs on the controller. I’m able to get the position and rotation of the contoller, even when held in the left hand. But the hardware buttons line trigger or bumper are only registered when the controller is in the right hand.

---

<div class="post-metadata">

**Author:** ![magicbot](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.magicleap.cloud/magicbot/32/2470_2.png) [@magicbot](https://forum.magicleap.cloud/u/magicbot)\
**Post date:** [July 24, 2025, 4:59pm UTC](https://forum.magicleap.cloud/t/controller-position-only-works-in-right-hand/6097/5 "2025-07-24T16:59:13Z")

</div>

The scripts in the main branch are actually the latest scripts. It’s just that the release page has not been updated to show this. Using the Magic Leap Hub or the npm package will import the latest version of the package: [Configure Project Settings | MagicLeap Developer Documentation](https://developer-docs.magicleap.cloud/docs/guides/unity-openxr/getting-started/configure-unity-settings/#import-magic-leap-unity-sdk)

* * *

Does the following script work for you in your project?

> **[Quick Start | MagicLeap Developer Documentation](https://developer-docs.magicleap.cloud/docs/guides/unity-openxr/controller/quick-start/quick-start-overview/#binding-input-actions)**
>
> This section covers how to use the Magic Leap 2 Controller Interaction Profile with Input System. For more information about obtaining OpenXR Input see Unity's OpenXR Input Documentation.

---

<div class="post-metadata">

**Author:** ![ArDevKarl](https://avatars.discourse-cdn.com/v4/letter/a/7ea924/32.png) [@ArDevKarl](https://forum.magicleap.cloud/u/ArDevKarl)\
**Post date:** [July 25, 2025, 7:03am UTC](https://forum.magicleap.cloud/t/controller-position-only-works-in-right-hand/6097/6 "2025-07-25T07:03:32Z")

</div>

I solved it myself. The problem seems to be that the default InputActions in the SDK are all routed to the RightHand (even in the latest 2.6). If anyone stumbles upon this issue, feel free to use this code (AI won’t solve this for you 😉 )

```auto
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;

    public class LeapControllerInputHandler : MonoSingleton<LeapControllerInputHandler>
    {
        public UnityEvent<bool> OnControllerActive = new();
        public UnityEvent OnTriggerDown = new();
        public UnityEvent OnTriggerUp = new();
        public UnityEvent OnBumperDown = new();
        public UnityEvent OnBumperUp = new();
        public UnityEvent OnMenuDown = new();
        public UnityEvent OnMenuUp = new();

        // TODO: Implement Trackpad if needed

        private void Start()
        {
            var controllerMap = _inputActions.FindActionMap("Controller", true);

            _bumperAction = controllerMap.FindAction("Bumper", true);
            _bumperAction.started += (_) => OnBumperDown.Invoke();
            _bumperAction.canceled += (_) => OnBumperUp.Invoke();
            _bumperAction.Enable();

            _triggerAction = controllerMap.FindAction("Trigger", true);
            _triggerAction.started += (_) => OnTriggerDown.Invoke();
            _triggerAction.canceled += (_) => OnTriggerUp.Invoke();
            _triggerAction.Enable();

            _triggerValueAction = controllerMap.FindAction("TriggerValue", true);
            _triggerValueAction.Enable();

            _menuAction = controllerMap.FindAction("MenuButton", true);
            _menuAction.started += (_) => OnMenuDown.Invoke();
            _menuAction.canceled += (_) => OnMenuUp.Invoke();
            _menuAction.Enable();

            _positionAction = controllerMap.FindAction("Position", true);
            _positionAction.Enable();

            _rotationAction = controllerMap.FindAction("Rotation", true);
            _rotationAction.Enable();

            _isTrackedAction = controllerMap.FindAction("IsTracked", true);
            _isTrackedAction.started += (_) => ControllerActive = true;
            _isTrackedAction.canceled += (_) => ControllerActive = false;
            _isTrackedAction.Enable();
        }

        public bool ControllerActive
        {
            get => _controllerActive;
            private set
            {
                if (value != _controllerActive)
                {
                    OnControllerActive.Invoke(value);
                    var state = value ? "ON" : "OFF";
                    Debug.Log($"Controller {state}");
                }
                _controllerActive = value;
            }
        }

        public Vector3 ControllerPosition() => _positionAction.ReadValue<Vector3>();
        public Quaternion ControllerRotation() => _positionAction.ReadValue<Quaternion>();
        public float TriggerValue() => _triggerValueAction.ReadValue<float>();

        [SerializeField] private InputActionAsset _inputActions;
        private bool _controllerActive;
        private InputAction _bumperAction;
        private InputAction _triggerAction;
        private InputAction _menuAction;
        private InputAction _positionAction;
        private InputAction _rotationAction;
        private InputAction _isTrackedAction;
        private InputAction _triggerValueAction;
    }

```

Just add this class to your scene and link it to the “MagicLeapInputsOpenXR” InputAsset. Using a different InputAsset may require to adjust the binding names.

---

<div class="post-metadata">

**Author:** ![whebert](https://avatars.discourse-cdn.com/v4/letter/w/3bc359/32.png) [@whebert](https://forum.magicleap.cloud/u/whebert)\
**Post date:** [July 31, 2025, 6:57pm UTC](https://forum.magicleap.cloud/t/controller-position-only-works-in-right-hand/6097/7 "2025-07-31T18:57:49Z")

</div>

Hello @ArDevKarl ,

Were you using the OpenXR version of the ML MRTK Rig and/or choosing the OpenXR automatic rig configuration option in the ML MRTK3 settings to configure the default MRTK Rig? That rig should be pre-configured to work with the new input actions and to properly receive input from the controller, regardless of which hand is holding it, with recent ML SDK package versions.
