From 9bc4362562294329008f6225a59fae6c4cd26d99 Mon Sep 17 00:00:00 2001 From: Rita Merkl Date: Mon, 2 Jun 2025 16:37:21 +0200 Subject: [PATCH 1/5] added test for adding device late --- Assets/Tests/InputSystem/Plugins/XRTests.cs | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/Assets/Tests/InputSystem/Plugins/XRTests.cs b/Assets/Tests/InputSystem/Plugins/XRTests.cs index d222dd26b2..768734a795 100644 --- a/Assets/Tests/InputSystem/Plugins/XRTests.cs +++ b/Assets/Tests/InputSystem/Plugins/XRTests.cs @@ -1,6 +1,7 @@ // ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled. #if ENABLE_VR || UNITY_GAMECORE using System; +using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using NUnit.Framework; @@ -11,6 +12,7 @@ using UnityEngine.InputSystem.LowLevel; using UnityEngine.InputSystem.Utilities; using UnityEngine.InputSystem.XR; +using UnityEngine.TestTools; using UnityEngine.XR; using Usages = UnityEngine.InputSystem.CommonUsages; @@ -629,6 +631,57 @@ public void Components_TrackedPoseDriver_DoesNotEnableOrDisableReferenceActions( Assert.That(trackingStateInput.action.enabled, Is.False); } + [UnityTest] + [Category("Components")] + public IEnumerator LateAddedXRControllerCanLinkTrackedPoseDriver() + { + var go = new GameObject(); + var tpd = go.AddComponent(); + tpd.updateType = TrackedPoseDriver.UpdateType.UpdateAndBeforeRender; + tpd.trackingType = TrackedPoseDriver.TrackingType.RotationAndPosition; + tpd.ignoreTrackingState = false; + var transform = tpd.transform; + + var positionAction = new InputAction(binding: "/devicePosition"); + var rotationAction = new InputAction(binding: "/deviceRotation"); + var trackingStateAction = new InputAction(binding: "/trackingState"); + tpd.positionInput = new InputActionProperty(positionAction); + tpd.rotationInput = new InputActionProperty(rotationAction); + tpd.trackingStateInput = new InputActionProperty(trackingStateAction); + + yield return null; + + Assert.That(positionAction.controls.Count, Is.EqualTo(0)); + Assert.That(rotationAction.controls.Count, Is.EqualTo(0)); + + var device = InputSystem.AddDevice(); + InputSystem.AddDeviceUsage(device, "RightHand"); + + yield return null; + + Assert.That(positionAction.controls.Count, Is.EqualTo(1)); + Assert.That(rotationAction.controls.Count, Is.EqualTo(1)); + + var position = new Vector3(1f, 2f, 3f); + var rotation = new Quaternion(0.09853293f, 0.09853293f, 0.09853293f, 0.9853293f); + using (StateEvent.From(device, out var stateEvent)) + { + device.devicePosition.WriteValueIntoEvent(position, stateEvent); + device.deviceRotation.WriteValueIntoEvent(rotation, stateEvent); + device.trackingState.WriteValueIntoEvent((int)(InputTrackingState.Position | InputTrackingState.Rotation), stateEvent); + + transform.position = Vector3.zero; + transform.rotation = Quaternion.identity; + InputSystem.QueueEvent(stateEvent); + InputSystem.Update(InputUpdateType.Dynamic); + } + + yield return null; + + Assert.That(transform.position, Is.EqualTo(position)); + Assert.That(transform.rotation, Is.EqualTo(rotation)); + } + [Test] [Category("Components")] public void Components_TrackedPoseDriver_RequiresResolvedTrackingStateBindings() From 7fae50edddd0f567b54c16ab85ea18c97f252c6f Mon Sep 17 00:00:00 2001 From: Rita Merkl Date: Mon, 2 Jun 2025 17:52:30 +0200 Subject: [PATCH 2/5] edited test to fit bug cause --- Assets/Tests/InputSystem/Plugins/XRTests.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Assets/Tests/InputSystem/Plugins/XRTests.cs b/Assets/Tests/InputSystem/Plugins/XRTests.cs index 768734a795..6f0e9cd1fd 100644 --- a/Assets/Tests/InputSystem/Plugins/XRTests.cs +++ b/Assets/Tests/InputSystem/Plugins/XRTests.cs @@ -633,7 +633,7 @@ public void Components_TrackedPoseDriver_DoesNotEnableOrDisableReferenceActions( [UnityTest] [Category("Components")] - public IEnumerator LateAddedXRControllerCanLinkTrackedPoseDriver() + public IEnumerator CanUseTrackedPoseDriverWithoutTrackingAction() { var go = new GameObject(); var tpd = go.AddComponent(); @@ -644,10 +644,8 @@ public IEnumerator LateAddedXRControllerCanLinkTrackedPoseDriver() var positionAction = new InputAction(binding: "/devicePosition"); var rotationAction = new InputAction(binding: "/deviceRotation"); - var trackingStateAction = new InputAction(binding: "/trackingState"); tpd.positionInput = new InputActionProperty(positionAction); tpd.rotationInput = new InputActionProperty(rotationAction); - tpd.trackingStateInput = new InputActionProperty(trackingStateAction); yield return null; @@ -668,7 +666,6 @@ public IEnumerator LateAddedXRControllerCanLinkTrackedPoseDriver() { device.devicePosition.WriteValueIntoEvent(position, stateEvent); device.deviceRotation.WriteValueIntoEvent(rotation, stateEvent); - device.trackingState.WriteValueIntoEvent((int)(InputTrackingState.Position | InputTrackingState.Rotation), stateEvent); transform.position = Vector3.zero; transform.rotation = Quaternion.identity; From d45a36b31520002ec35b5219d7fe7c7244ae7414 Mon Sep 17 00:00:00 2001 From: Rita Merkl Date: Tue, 3 Jun 2025 11:04:46 +0200 Subject: [PATCH 3/5] update tracking state according to device changes --- .../Plugins/XR/TrackedPoseDriver.cs | 56 +++++++++++++------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/TrackedPoseDriver.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/TrackedPoseDriver.cs index 56e914af04..05382d7e80 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/TrackedPoseDriver.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/TrackedPoseDriver.cs @@ -432,6 +432,7 @@ protected virtual void Awake() protected void OnEnable() { InputSystem.onAfterUpdate += UpdateCallback; + InputSystem.onDeviceChange += OnDeviceChanged; BindActions(); // Read current input values when becoming enabled, @@ -446,6 +447,7 @@ protected void OnDisable() { UnbindActions(); InputSystem.onAfterUpdate -= UpdateCallback; + InputSystem.onDeviceChange -= OnDeviceChanged; } /// @@ -484,7 +486,7 @@ protected void UpdateCallback() else m_CurrentRotation = transform.localRotation; - ReadTrackingState(hasResolvedPositionInputControl, hasResolvedRotationInputControl); + ReadTrackingState(); m_IsFirstUpdate = false; } @@ -495,7 +497,38 @@ protected void UpdateCallback() OnUpdate(); } - void ReadTrackingState(bool hasResolvedPositionInputControl, bool hasResolvedRotationInputControl) + void OnDeviceChanged(InputDevice inputDevice, InputDeviceChange inputDeviceChange) + { + ReadTrackingStateWithoutTrackingAction(); + } + + /// + /// React to changes of devices to stop the tracking of position / rotation or both if a device is removed, starts the tracking if + /// a device is added. + /// + void ReadTrackingStateWithoutTrackingAction() + { + var trackingStateAction = m_TrackingStateInput.action; + if (trackingStateAction != null && trackingStateAction.m_BindingsCount != 0) + return; + + var hasResolvedPositionInputControl = HasResolvedControl(m_PositionInput.action); + var hasResolvedRotationInputControl = HasResolvedControl(m_RotationInput.action); + + // Treat an Input Action Reference with no reference the same as + // an enabled Input Action with no authored bindings, and allow driving the Transform pose. + // Check if we have transform and rotation controls to drive the pose. + if (hasResolvedPositionInputControl && hasResolvedRotationInputControl) + m_CurrentTrackingState = TrackingStates.Position | TrackingStates.Rotation; + else if (hasResolvedPositionInputControl) + m_CurrentTrackingState = TrackingStates.Position; + else if (hasResolvedRotationInputControl) + m_CurrentTrackingState = TrackingStates.Rotation; + else + m_CurrentTrackingState = TrackingStates.None; + } + + void ReadTrackingState() { var trackingStateAction = m_TrackingStateInput.action; if (trackingStateAction != null && !trackingStateAction.enabled) @@ -504,29 +537,16 @@ void ReadTrackingState(bool hasResolvedPositionInputControl, bool hasResolvedRot m_CurrentTrackingState = TrackingStates.None; return; } - - if (trackingStateAction == null || trackingStateAction.m_BindingsCount == 0) - { - // Treat an Input Action Reference with no reference the same as - // an enabled Input Action with no authored bindings, and allow driving the Transform pose. - // Check if we have transform and rotation controls to drive the pose. - if (hasResolvedPositionInputControl && hasResolvedRotationInputControl) - m_CurrentTrackingState = TrackingStates.Position | TrackingStates.Rotation; - else if (hasResolvedPositionInputControl) - m_CurrentTrackingState = TrackingStates.Position; - else if (hasResolvedRotationInputControl) - m_CurrentTrackingState = TrackingStates.Rotation; - else - m_CurrentTrackingState = TrackingStates.None; - } - else if (HasResolvedControl(trackingStateAction)) + if (HasResolvedControl(trackingStateAction)) { // Retain the current value if there is no resolved binding. // Since the field initializes to allowing position and rotation, // this allows for driving the Transform pose always when the device // doesn't support reporting the tracking state. m_CurrentTrackingState = (TrackingStates)trackingStateAction.ReadValue(); + return; } + ReadTrackingStateWithoutTrackingAction(); } /// From 0794cde43fadb224b62bc76e8dcaa0ce9df81ce5 Mon Sep 17 00:00:00 2001 From: Rita Merkl Date: Tue, 3 Jun 2025 11:13:40 +0200 Subject: [PATCH 4/5] added changelog --- Packages/com.unity.inputsystem/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 7479fcbc14..e5c0152f75 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -26,6 +26,7 @@ however, it has to be formatted properly to pass verification tests. - Fixed PlayerInput component automatically switching away from the default ActionMap set to 'None'. - Fixed a console error being shown when targeting visionOS builds in 2022.3. - Fixed a Tap Interaction issue with analog controls. The Tap interaction would keep re-starting after timeout. [ISXB-627](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-627) +- Fixed TrackedPoseDriver stops updating position and rotation when device is added after its initialization. [ISXB-1555](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1555) ## [1.14.0] - 2025-03-20 From 4197723e0301fd730395e15f26b3ab87f705a231 Mon Sep 17 00:00:00 2001 From: Rita Merkl Date: Fri, 6 Jun 2025 12:13:47 +0200 Subject: [PATCH 5/5] don't update tracking state on device change before initialisation --- .../InputSystem/Plugins/XR/TrackedPoseDriver.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/TrackedPoseDriver.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/TrackedPoseDriver.cs index 05382d7e80..f4b9e1decc 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/TrackedPoseDriver.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/TrackedPoseDriver.cs @@ -499,6 +499,8 @@ protected void UpdateCallback() void OnDeviceChanged(InputDevice inputDevice, InputDeviceChange inputDeviceChange) { + if (m_IsFirstUpdate) + return; ReadTrackingStateWithoutTrackingAction(); }