Rotation is inversed for left hand vs right hand interactivity - Immersive Bounded Mode

Hello friends,

I have a problem with hands interactivity in Vision Pro Mixed Reality Bounded mode.
I have an object to rotate in space along the Y-axis. If I rotate it with the right hand, everything works as intended. But if I rotate it with the left hand, the rotation is reversed for no reason. Most people are right-handed, and this issue does not affect them, but the client who commissioned this project is left-handed, so it’s a discriminatory bummer that needs to be resolved.

It’s impossible to trace the issue in the Simulator or the Unity editor; it can only be observed on an actual device. I assume the Simulator only represents the right hand?

Could you advise on how to make both hands act normally? If you rotate the object to the left, the object rotates to the left regardless of which hand is used.

This is the script I made (based on the Manipulation Polyspatial sample):

using System.Collections.Generic;
using Unity.PolySpatial.InputDevices;
using UnityEngine;
using UnityEngine.InputSystem.EnhancedTouch;
using UnityEngine.InputSystem.LowLevel;

namespace PolySpatial.Samples
{
    public class BHS_ManipulationInputManager : MonoBehaviour
    {
        struct Selection
        {
            public bhs_PieceSelectionBehavior Piece;
            public Quaternion InitialHandRotation;
            public Quaternion InitialObjectRotation;
            public Quaternion TargetRotation;
            public bool ShouldRotate;
            public float LerpTime; // Add a lerp time for smooth interpolation
        }

        internal const int k_Deselected = -1;
        readonly Dictionary<int, Selection> m_CurrentSelections = new();

        [SerializeField]
        private float rotationSpeedMultiplier = 2.0f; // Adjust this value to control rotation speed
        [SerializeField]
        private float lerpSpeed = 5.0f; // Control the speed of the interpolation

        void OnEnable()
        {
            EnhancedTouchSupport.Enable();
        }

        void Update()
        {
            foreach (var touch in UnityEngine.InputSystem.EnhancedTouch.Touch.activeTouches)
            {
                var spatialPointerState = EnhancedSpatialPointerSupport.GetPointerState(touch);
                var interactionId = spatialPointerState.interactionId;
                var pieceObject = spatialPointerState.targetObject;

                if (pieceObject != null)
                {
                    if (pieceObject.TryGetComponent(out bhs_PieceSelectionBehavior piece) && piece.selectingPointer == -1)
                    {
                        var pieceTransform = piece.transform;
                        piece.SetSelected(interactionId);

                        if (m_CurrentSelections.TryGetValue(interactionId, out var existingSelection))
                            existingSelection.Piece.SetSelected(k_Deselected);

                        m_CurrentSelections[interactionId] = new Selection
                        {
                            Piece = piece,
                            InitialHandRotation = spatialPointerState.inputDeviceRotation,
                            InitialObjectRotation = pieceTransform.rotation,
                            TargetRotation = pieceTransform.rotation,
                            ShouldRotate = false,
                            LerpTime = 0f // Initialize LerpTime
                        };
                    }
                }

                if (m_CurrentSelections.TryGetValue(interactionId, out var selection))
                {
                    switch (spatialPointerState.phase)
                    {
                        case SpatialPointerPhase.Moved:
                            var currentHandRotation = spatialPointerState.inputDeviceRotation;
                            var rotationDifference = Quaternion.Inverse(selection.InitialHandRotation) * currentHandRotation;

                            // Extract Y component, reverse and amplify the direction
                            var yRotation = -rotationDifference.eulerAngles.y * rotationSpeedMultiplier;

                            // Apply the amplified Y-axis rotation
                            var newYRotation = Quaternion.Euler(0f, yRotation, 0f);
                            selection.TargetRotation = selection.InitialObjectRotation * newYRotation;
                            selection.ShouldRotate = true;
                            m_CurrentSelections[interactionId] = selection;
                            break;
                        case SpatialPointerPhase.None:
                        case SpatialPointerPhase.Ended:
                        case SpatialPointerPhase.Cancelled:
                            selection.ShouldRotate = false;
                            m_CurrentSelections[interactionId] = selection;
                            DeselectPiece(interactionId);
                            break;
                    }
                }
            }

            // Smoothly apply rotation for each selected piece
            foreach (var key in new List<int>(m_CurrentSelections.Keys))
            {
                var selection = m_CurrentSelections[key];
                if (selection.Piece != null && selection.ShouldRotate)
                {
                    // Smoothly interpolate towards the target rotation
                    selection.Piece.transform.rotation = Quaternion.Lerp(selection.Piece.transform.rotation, selection.TargetRotation, Time.deltaTime * lerpSpeed);
                    m_CurrentSelections[key] = selection;
                }
            }
        }

        void DeselectPiece(int interactionId)
        {
            if (m_CurrentSelections.TryGetValue(interactionId, out var selection))
            {
                selection.Piece.SetSelected(k_Deselected);
                m_CurrentSelections.Remove(interactionId);
            }
        }
    }
}

I programmed rotation inverse in the script to make right-hand rotation in the correct direction. Otherwise, it was reversed for right-handed interaction.

The image shows the object I want to rotate around its Y-axis on the platform with either the left or the right hand.

Thank you for any help. I’ve been struggling to make it work to no avail.