From c562118cf434a058dc91f6084b5fb95405b4001e Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Tue, 17 Feb 2026 16:52:19 +0530 Subject: [PATCH 01/15] Added test to cover the fix. --- .../InputSystem/Plugins/InputForUITests.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index c279d7a157..878dbee010 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -92,6 +92,33 @@ public void InputSystemActionAssetIsNotNull() "Test is invalid since InputSystemProvider actions are not available"); } + [Test] + [Category(kTestCategory)] + public void Shutdown_DoesNotDisableProjectWideActionsAsset() + { + var asset = ScriptableObject.CreateInstance(); + var uiMap = new InputActionMap("UI"); + uiMap.AddAction("Point", InputActionType.PassThrough, "/position"); + uiMap.AddAction("Navigate", InputActionType.PassThrough, "/leftStick"); + uiMap.AddAction("Submit", InputActionType.Button, "/enter"); + uiMap.AddAction("Cancel", InputActionType.Button, "/escape"); + uiMap.AddAction("Click", InputActionType.PassThrough, "/leftButton"); + uiMap.AddAction("MiddleClick", InputActionType.PassThrough, "/middleButton"); + uiMap.AddAction("RightClick", InputActionType.PassThrough, "/rightButton"); + uiMap.AddAction("ScrollWheel", InputActionType.PassThrough, "/scroll"); + asset.AddActionMap(uiMap); + + InputSystem.s_Manager.actions = asset; + + m_InputSystemProvider.Initialize(); + Assert.That(asset.enabled, Is.True, "Project-wide actions should be enabled by provider initialization."); + + m_InputSystemProvider.Shutdown(); + Assert.That(asset.enabled, Is.True, "Project-wide actions must remain enabled after provider shutdown."); + + Object.DestroyImmediate(asset); + } + [Test] [Category(kTestCategory)] // Checks that mouse events are ignored when a touch is active. From 0ed73d817a657209950405eb9d6eb3396b3a4d33 Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Tue, 17 Feb 2026 16:52:37 +0530 Subject: [PATCH 02/15] Fix: Avoid disabling project-wide actions on shutdown --- .../InputSystem/Plugins/InputForUI/InputSystemProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs index 1b056f7e76..cfdfd07c98 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs @@ -664,7 +664,7 @@ void UnregisterActions() UnregisterAction(ref m_RightClickAction, OnRightClickPerformed); UnregisterAction(ref m_ScrollWheelAction, OnScrollWheelPerformed); - if (m_InputActionAsset != null) + if (m_InputActionAsset != null && m_InputActionAsset != InputSystem.actions) m_InputActionAsset.Disable(); } From 61807cc684c40eb3eaa5bcae778dc0a0c27a140f Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Tue, 3 Mar 2026 16:10:36 +0530 Subject: [PATCH 03/15] Fix test double shutdown call causing issues. --- Assets/Tests/InputSystem/Plugins/InputForUITests.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index 878dbee010..0075067a63 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -37,6 +37,7 @@ public class InputForUITests : InputTestFixture readonly List m_InputForUIEvents = new List(); private int m_CurrentInputEventToCheck; InputSystemProvider m_InputSystemProvider; + private bool m_ClearedMockProvider; private InputActionAsset storedActions; @@ -45,6 +46,7 @@ public override void Setup() { base.Setup(); m_CurrentInputEventToCheck = 0; + m_ClearedMockProvider = false; storedActions = InputSystem.actions; @@ -59,7 +61,8 @@ public override void Setup() public override void TearDown() { EventProvider.Unsubscribe(InputForUIOnEvent); - EventProvider.ClearMockProvider(); + if (!m_ClearedMockProvider) + EventProvider.ClearMockProvider(); m_InputForUIEvents.Clear(); InputSystem.s_Manager.actions = storedActions; @@ -113,7 +116,8 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() m_InputSystemProvider.Initialize(); Assert.That(asset.enabled, Is.True, "Project-wide actions should be enabled by provider initialization."); - m_InputSystemProvider.Shutdown(); + EventProvider.ClearMockProvider(); + m_ClearedMockProvider = true; Assert.That(asset.enabled, Is.True, "Project-wide actions must remain enabled after provider shutdown."); Object.DestroyImmediate(asset); From b087ccd1e8bb7aaebc4f0f15269ce0719f9f3d81 Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Mon, 23 Mar 2026 15:20:12 +0530 Subject: [PATCH 04/15] Fix InputForUI action lifecycle to only manage the UI action map. --- .../Plugins/InputForUI/InputSystemProvider.cs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs index cfdfd07c98..272994b1d5 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs @@ -17,6 +17,8 @@ internal class InputSystemProvider : IEventProviderImpl DefaultInputActions m_DefaultInputActions; InputActionAsset m_InputActionAsset; + InputActionMap m_UIActionMap; + bool m_ShouldDisableUIActionMapOnUnregister; // Note that these are plain action references instead since InputActionReference do // not provide any value when this integration doesn't have any UI. If this integration @@ -636,14 +638,11 @@ void RegisterActions() m_RightClickAction = FindActionAndRegisterCallback(Actions.RightClickAction, OnRightClickPerformed); m_ScrollWheelAction = FindActionAndRegisterCallback(Actions.ScrollWheelAction, OnScrollWheelPerformed); - // When adding new actions, don't forget to add them to UnregisterActions - if (InputSystem.actions == null) - { - // If we've not loaded a user-created set of actions, just enable the UI actions from our defaults. - m_InputActionAsset.FindActionMap("UI", true).Enable(); - } - else - m_InputActionAsset.Enable(); + // Only touch the UI map so we don't change the enabled state of unrelated maps. + m_UIActionMap = m_InputActionAsset?.FindActionMap("UI", true); + m_ShouldDisableUIActionMapOnUnregister = m_UIActionMap != null && !m_UIActionMap.enabled; + if (m_ShouldDisableUIActionMapOnUnregister) + m_UIActionMap.Enable(); } void UnregisterAction(ref InputAction action, Action callback = null) @@ -664,8 +663,11 @@ void UnregisterActions() UnregisterAction(ref m_RightClickAction, OnRightClickPerformed); UnregisterAction(ref m_ScrollWheelAction, OnScrollWheelPerformed); - if (m_InputActionAsset != null && m_InputActionAsset != InputSystem.actions) - m_InputActionAsset.Disable(); + if (m_ShouldDisableUIActionMapOnUnregister && m_UIActionMap != null) + m_UIActionMap.Disable(); + + m_UIActionMap = null; + m_ShouldDisableUIActionMapOnUnregister = false; } void SelectInputActionAsset() From 7c52dcef6c057d0e7d630fe0e184ad3788f3a392 Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Wed, 20 May 2026 02:05:19 +0530 Subject: [PATCH 05/15] Scope UI action map lifecycle to provider-owned assets and address u-pr comments. --- .../InputSystem/Plugins/InputForUITests.cs | 22 +++++++++++-------- .../Plugins/InputForUI/InputSystemProvider.cs | 9 +++++--- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index 4ad3e874dc..d39dfc13d0 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -111,16 +111,20 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() uiMap.AddAction("ScrollWheel", InputActionType.PassThrough, "/scroll"); asset.AddActionMap(uiMap); - InputSystem.s_Manager.actions = asset; - - m_InputSystemProvider.Initialize(); - Assert.That(asset.enabled, Is.True, "Project-wide actions should be enabled by provider initialization."); - - EventProvider.ClearMockProvider(); - m_ClearedMockProvider = true; - Assert.That(asset.enabled, Is.True, "Project-wide actions must remain enabled after provider shutdown."); + InputSystem.manager.actions = asset; + try + { + m_InputSystemProvider.Initialize(); + Assert.That(asset.enabled, Is.True, "Project-wide actions should be enabled by provider initialization."); - Object.DestroyImmediate(asset); + EventProvider.ClearMockProvider(); + m_ClearedMockProvider = true; + Assert.That(asset.enabled, Is.True, "Project-wide actions must remain enabled after provider shutdown."); + } + finally + { + Object.DestroyImmediate(asset); + } } [Test] diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs index 272994b1d5..60466236eb 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/InputForUI/InputSystemProvider.cs @@ -639,10 +639,13 @@ void RegisterActions() m_ScrollWheelAction = FindActionAndRegisterCallback(Actions.ScrollWheelAction, OnScrollWheelPerformed); // Only touch the UI map so we don't change the enabled state of unrelated maps. - m_UIActionMap = m_InputActionAsset?.FindActionMap("UI", true); - m_ShouldDisableUIActionMapOnUnregister = m_UIActionMap != null && !m_UIActionMap.enabled; - if (m_ShouldDisableUIActionMapOnUnregister) + m_UIActionMap = m_InputActionAsset?.FindActionMap("UI", false); + if (m_UIActionMap != null && !m_UIActionMap.enabled) + { + // Don't take ownership of the UI map lifecycle for project-wide actions — the user manages those. + m_ShouldDisableUIActionMapOnUnregister = m_InputActionAsset != InputSystem.actions; m_UIActionMap.Enable(); + } } void UnregisterAction(ref InputAction action, Action callback = null) From 17450d18a87974d46ae3d8dbe2d1c29cd0b96c0a Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Sat, 23 May 2026 02:53:00 +0530 Subject: [PATCH 06/15] Address PR comments and add changelog. --- Assets/Tests/InputSystem/Plugins/InputForUITests.cs | 4 ++-- Packages/com.unity.inputsystem/CHANGELOG.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index bcfeb9f8e4..f14a41729a 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -115,11 +115,11 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() try { m_InputSystemProvider.Initialize(); - Assert.That(asset.enabled, Is.True, "Project-wide actions should be enabled by provider initialization."); + Assert.That(uiMap.enabled, Is.True, "UI action map should be enabled by provider initialization."); EventProvider.ClearMockProvider(); m_ClearedMockProvider = true; - Assert.That(asset.enabled, Is.True, "Project-wide actions must remain enabled after provider shutdown."); + Assert.That(uiMap.enabled, Is.True, "UI action map must remain enabled after provider shutdown."); } finally { diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 02a6867477..14e27636f1 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed +- Fixed `InputSystemProvider` disabling project-wide actions on shutdown when UI Toolkit destroys its objects mid-play. The provider now scopes its lifecycle to the UI action map only and does not disable project-wide actions [UUM-134130](https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-134130) - Fixed `InputActionRebindingExtensions.GetBindingDisplayString(InputAction, InputBinding, ...)` returning an empty string for composite bindings when the binding mask filters by group [UUM-141423](https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-141423) - Fixed `InputEventPtr.handled` not preventing actions from triggering when switching devices. The default event handled policy has been changed from `SuppressStateUpdates` (now deprecated) to `SuppressActionEventNotifications`, which keeps device state synchronized while suppressing action callbacks for handled events. [ISXB-1097](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1097) - Fixed all `InputAction.WasXxxThisFrame()` and `WasXxxThisDynamicUpdate()` polling APIs to use per-action suppression tracking instead of a map-wide flag. Previously, when multiple events arrived in the same frame with mixed handled/unhandled states, the last event's suppression state could incorrectly affect all actions in the map. [ISXB-1097](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1097) From 0acc80888f655a0ee17421be2af7509f7f05de5d Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Tue, 26 May 2026 19:52:58 +0530 Subject: [PATCH 07/15] track UI action map enablement independent of asset ownership --- .../Runtime/Plugins/InputForUI/InputSystemProvider.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Runtime/Plugins/InputForUI/InputSystemProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Runtime/Plugins/InputForUI/InputSystemProvider.cs index 60466236eb..a5f47baedf 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Runtime/Plugins/InputForUI/InputSystemProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Runtime/Plugins/InputForUI/InputSystemProvider.cs @@ -642,8 +642,11 @@ void RegisterActions() m_UIActionMap = m_InputActionAsset?.FindActionMap("UI", false); if (m_UIActionMap != null && !m_UIActionMap.enabled) { - // Don't take ownership of the UI map lifecycle for project-wide actions — the user manages those. - m_ShouldDisableUIActionMapOnUnregister = m_InputActionAsset != InputSystem.actions; + // We enabled the map, so we are responsible for restoring it on shutdown. + // This applies to both provider-owned assets and project-wide actions: if the + // user had the UI map disabled before initialization, we must not leave it + // permanently enabled after the provider goes away. + m_ShouldDisableUIActionMapOnUnregister = true; m_UIActionMap.Enable(); } } From 20e7f4eb663ac6bf7b1efa560afb1b54e311c034 Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Wed, 27 May 2026 10:09:00 +0530 Subject: [PATCH 08/15] Fix; New Tests; - Correct and extend provider shutdown tests for per-map enablement tracking --- .../InputSystem/Plugins/InputForUITests.cs | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index f14a41729a..eb6f8dae94 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -65,6 +65,7 @@ public override void TearDown() EventProvider.ClearMockProvider(); m_InputForUIEvents.Clear(); + // InputSystem.actions setter throws in play mode, so we use the internal manager property here. InputSystem.manager.actions = storedActions; #if UNITY_EDITOR @@ -100,6 +101,13 @@ public void InputSystemActionAssetIsNotNull() public void Shutdown_DoesNotDisableProjectWideActionsAsset() { var asset = ScriptableObject.CreateInstance(); + + // A non-UI map the user has enabled — provider must never touch it. + var gameplayMap = new InputActionMap("Gameplay"); + gameplayMap.AddAction("Jump", InputActionType.Button, "/space"); + asset.AddActionMap(gameplayMap); + gameplayMap.Enable(); + var uiMap = new InputActionMap("UI"); uiMap.AddAction("Point", InputActionType.PassThrough, "/position"); uiMap.AddAction("Navigate", InputActionType.PassThrough, "/leftStick"); @@ -111,15 +119,57 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() uiMap.AddAction("ScrollWheel", InputActionType.PassThrough, "/scroll"); asset.AddActionMap(uiMap); + // InputSystem.actions setter throws in play mode, so we use the internal manager property here. InputSystem.manager.actions = asset; try { m_InputSystemProvider.Initialize(); Assert.That(uiMap.enabled, Is.True, "UI action map should be enabled by provider initialization."); + Assert.That(gameplayMap.enabled, Is.True, "Provider must not change enabled state of non-UI maps."); + + EventProvider.ClearMockProvider(); + m_ClearedMockProvider = true; + + // The UI map was disabled before initialization; the provider enabled it, so it must + // restore it to disabled on shutdown. Non-UI maps must remain untouched. + Assert.That(uiMap.enabled, Is.False, "UI action map should be restored to disabled after provider shutdown, since it was disabled before initialization."); + Assert.That(gameplayMap.enabled, Is.True, "Provider must not disable non-UI maps on shutdown."); + } + finally + { + Object.DestroyImmediate(asset); + } + } + + [Test] + [Category(kTestCategory)] + public void Shutdown_DoesNotDisableProjectWideUIMap_WhenAlreadyEnabledBeforeInit() + { + var asset = ScriptableObject.CreateInstance(); + var uiMap = new InputActionMap("UI"); + uiMap.AddAction("Point", InputActionType.PassThrough, "/position"); + uiMap.AddAction("Navigate", InputActionType.PassThrough, "/leftStick"); + uiMap.AddAction("Submit", InputActionType.Button, "/enter"); + uiMap.AddAction("Cancel", InputActionType.Button, "/escape"); + uiMap.AddAction("Click", InputActionType.PassThrough, "/leftButton"); + uiMap.AddAction("MiddleClick", InputActionType.PassThrough, "/middleButton"); + uiMap.AddAction("RightClick", InputActionType.PassThrough, "/rightButton"); + uiMap.AddAction("ScrollWheel", InputActionType.PassThrough, "/scroll"); + asset.AddActionMap(uiMap); + uiMap.Enable(); // User had the UI map enabled before the provider started. + + // InputSystem.actions setter throws in play mode, so we use the internal manager property here. + InputSystem.manager.actions = asset; + try + { + m_InputSystemProvider.Initialize(); + Assert.That(uiMap.enabled, Is.True, "UI action map should remain enabled after provider initialization."); EventProvider.ClearMockProvider(); m_ClearedMockProvider = true; - Assert.That(uiMap.enabled, Is.True, "UI action map must remain enabled after provider shutdown."); + + // The provider did not enable the map, so it must not disable it on shutdown. + Assert.That(uiMap.enabled, Is.True, "UI action map must remain enabled after provider shutdown when the user had it enabled before initialization."); } finally { @@ -127,6 +177,28 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() } } + [Test] + [Category(kTestCategory)] + public void Shutdown_DisablesUIActionMap_ForProviderOwnedAsset() + { + InputActionMap capturedUIMap = null; + InputSystemProvider.SetOnRegisterActions(asset => + capturedUIMap = asset?.FindActionMap("UI", false)); + + // Remove project-wide actions so the provider falls back to its own internal default asset. + // InputSystem.actions setter throws in play mode, so we use the internal manager property here. + InputSystem.manager.actions = null; + m_InputSystemProvider.Initialize(); + InputSystemProvider.SetOnRegisterActions(null); + + Assert.That(capturedUIMap, Is.Not.Null, "Provider should have a UI action map in its internal default asset."); + Assert.That(capturedUIMap.enabled, Is.True, "UI action map should be enabled by provider initialization."); + + EventProvider.ClearMockProvider(); + m_ClearedMockProvider = true; + Assert.That(capturedUIMap.enabled, Is.False, "UI action map should be disabled after provider shutdown for provider-owned assets."); + } + [Test] [Category(kTestCategory)] // Checks that mouse events are ignored when a touch is active. From 93e82fb77d328616f7cae09a7625ec1fab385fd0 Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Wed, 27 May 2026 11:37:58 +0530 Subject: [PATCH 09/15] Missed change due to test failure locally. --- Assets/Tests/InputSystem/Plugins/InputForUITests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index eb6f8dae94..02580b4700 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -106,7 +106,6 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() var gameplayMap = new InputActionMap("Gameplay"); gameplayMap.AddAction("Jump", InputActionType.Button, "/space"); asset.AddActionMap(gameplayMap); - gameplayMap.Enable(); var uiMap = new InputActionMap("UI"); uiMap.AddAction("Point", InputActionType.PassThrough, "/position"); @@ -119,6 +118,9 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() uiMap.AddAction("ScrollWheel", InputActionType.PassThrough, "/scroll"); asset.AddActionMap(uiMap); + // Enable after all maps are added; modifying the asset while any map is enabled is not allowed. + gameplayMap.Enable(); + // InputSystem.actions setter throws in play mode, so we use the internal manager property here. InputSystem.manager.actions = asset; try From c9fbf6a7a9ac100f9123ef604af092b2738afd82 Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Wed, 27 May 2026 12:04:50 +0530 Subject: [PATCH 10/15] Fix test failures --- Assets/Tests/InputSystem/Plugins/InputForUITests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index 02580b4700..0ab2ffca33 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -129,7 +129,9 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() Assert.That(uiMap.enabled, Is.True, "UI action map should be enabled by provider initialization."); Assert.That(gameplayMap.enabled, Is.True, "Provider must not change enabled state of non-UI maps."); - EventProvider.ClearMockProvider(); + // Call Shutdown directly: ClearMockProvider reinstates the real provider which + // calls RegisterActions() and re-enables the UI map, masking the behavior under test. + m_InputSystemProvider.Shutdown(); m_ClearedMockProvider = true; // The UI map was disabled before initialization; the provider enabled it, so it must From dc11f07fbeb95f71b4eb6008f88109c4cab20d4c Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Wed, 27 May 2026 18:00:46 +0530 Subject: [PATCH 11/15] For provider-owned assets the cleanup still applies (disable on shutdown). For project-wide actions the play-mode lifecycle owns the asset, so the provider enables the UI map on init but leaves it as-is when shutting down. --- .../InputSystem/Plugins/InputForUITests.cs | 49 ++++++------------- .../Plugins/InputForUI/InputSystemProvider.cs | 11 +++-- 2 files changed, 22 insertions(+), 38 deletions(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index 0ab2ffca33..d5c687ac08 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -96,47 +96,40 @@ public void InputSystemActionAssetIsNotNull() "Test is invalid since InputSystemProvider actions are not available"); } + // SelectInputActionAsset() only requires a map named "UI" to exist; no specific + // actions are needed for the provider lifecycle tests. + static InputActionAsset CreateProjectWideAssetWithUIMap(out InputActionMap uiMap) + { + var asset = ScriptableObject.CreateInstance(); + uiMap = new InputActionMap("UI"); + asset.AddActionMap(uiMap); + return asset; + } + [Test] [Category(kTestCategory)] public void Shutdown_DoesNotDisableProjectWideActionsAsset() { - var asset = ScriptableObject.CreateInstance(); + var asset = CreateProjectWideAssetWithUIMap(out var uiMap); // A non-UI map the user has enabled — provider must never touch it. var gameplayMap = new InputActionMap("Gameplay"); gameplayMap.AddAction("Jump", InputActionType.Button, "/space"); asset.AddActionMap(gameplayMap); - - var uiMap = new InputActionMap("UI"); - uiMap.AddAction("Point", InputActionType.PassThrough, "/position"); - uiMap.AddAction("Navigate", InputActionType.PassThrough, "/leftStick"); - uiMap.AddAction("Submit", InputActionType.Button, "/enter"); - uiMap.AddAction("Cancel", InputActionType.Button, "/escape"); - uiMap.AddAction("Click", InputActionType.PassThrough, "/leftButton"); - uiMap.AddAction("MiddleClick", InputActionType.PassThrough, "/middleButton"); - uiMap.AddAction("RightClick", InputActionType.PassThrough, "/rightButton"); - uiMap.AddAction("ScrollWheel", InputActionType.PassThrough, "/scroll"); - asset.AddActionMap(uiMap); - - // Enable after all maps are added; modifying the asset while any map is enabled is not allowed. - gameplayMap.Enable(); + gameplayMap.Enable(); // Enable after all maps are added; modifying the asset while any map is enabled is not allowed. // InputSystem.actions setter throws in play mode, so we use the internal manager property here. InputSystem.manager.actions = asset; try { m_InputSystemProvider.Initialize(); - Assert.That(uiMap.enabled, Is.True, "UI action map should be enabled by provider initialization."); + Assert.That(uiMap.enabled, Is.True, "UI action map should be enabled by provider initialization."); Assert.That(gameplayMap.enabled, Is.True, "Provider must not change enabled state of non-UI maps."); - // Call Shutdown directly: ClearMockProvider reinstates the real provider which - // calls RegisterActions() and re-enables the UI map, masking the behavior under test. - m_InputSystemProvider.Shutdown(); + EventProvider.ClearMockProvider(); m_ClearedMockProvider = true; - // The UI map was disabled before initialization; the provider enabled it, so it must - // restore it to disabled on shutdown. Non-UI maps must remain untouched. - Assert.That(uiMap.enabled, Is.False, "UI action map should be restored to disabled after provider shutdown, since it was disabled before initialization."); + Assert.That(uiMap.enabled, Is.True, "Provider must not disable the UI map in a project-wide asset on shutdown."); Assert.That(gameplayMap.enabled, Is.True, "Provider must not disable non-UI maps on shutdown."); } finally @@ -149,17 +142,7 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() [Category(kTestCategory)] public void Shutdown_DoesNotDisableProjectWideUIMap_WhenAlreadyEnabledBeforeInit() { - var asset = ScriptableObject.CreateInstance(); - var uiMap = new InputActionMap("UI"); - uiMap.AddAction("Point", InputActionType.PassThrough, "/position"); - uiMap.AddAction("Navigate", InputActionType.PassThrough, "/leftStick"); - uiMap.AddAction("Submit", InputActionType.Button, "/enter"); - uiMap.AddAction("Cancel", InputActionType.Button, "/escape"); - uiMap.AddAction("Click", InputActionType.PassThrough, "/leftButton"); - uiMap.AddAction("MiddleClick", InputActionType.PassThrough, "/middleButton"); - uiMap.AddAction("RightClick", InputActionType.PassThrough, "/rightButton"); - uiMap.AddAction("ScrollWheel", InputActionType.PassThrough, "/scroll"); - asset.AddActionMap(uiMap); + var asset = CreateProjectWideAssetWithUIMap(out var uiMap); uiMap.Enable(); // User had the UI map enabled before the provider started. // InputSystem.actions setter throws in play mode, so we use the internal manager property here. diff --git a/Packages/com.unity.inputsystem/InputSystem/Runtime/Plugins/InputForUI/InputSystemProvider.cs b/Packages/com.unity.inputsystem/InputSystem/Runtime/Plugins/InputForUI/InputSystemProvider.cs index a5f47baedf..cbc8f53901 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Runtime/Plugins/InputForUI/InputSystemProvider.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Runtime/Plugins/InputForUI/InputSystemProvider.cs @@ -642,12 +642,13 @@ void RegisterActions() m_UIActionMap = m_InputActionAsset?.FindActionMap("UI", false); if (m_UIActionMap != null && !m_UIActionMap.enabled) { - // We enabled the map, so we are responsible for restoring it on shutdown. - // This applies to both provider-owned assets and project-wide actions: if the - // user had the UI map disabled before initialization, we must not leave it - // permanently enabled after the provider goes away. - m_ShouldDisableUIActionMapOnUnregister = true; m_UIActionMap.Enable(); + + // For provider-owned assets we are responsible for cleanup on shutdown. + // For project-wide actions the play-mode lifecycle manages the asset, so + // leave it as-is when the provider goes away. + if (m_InputActionAsset != InputSystem.actions) + m_ShouldDisableUIActionMapOnUnregister = true; } } From 2b5eadff88cd6de12c98f9f1ae2bec03468af3db Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Wed, 27 May 2026 18:15:33 +0530 Subject: [PATCH 12/15] Update test action asset. --- Assets/Tests/InputSystem/Plugins/InputForUITests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index d5c687ac08..128189f41b 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -96,12 +96,14 @@ public void InputSystemActionAssetIsNotNull() "Test is invalid since InputSystemProvider actions are not available"); } - // SelectInputActionAsset() only requires a map named "UI" to exist; no specific - // actions are needed for the provider lifecycle tests. + // Creates a minimal project-wide asset recognised by SelectInputActionAsset(). + // At least one action is required: InputActionMap.enabled is m_EnabledActionsCount > 0, + // so an empty map can never report as enabled. static InputActionAsset CreateProjectWideAssetWithUIMap(out InputActionMap uiMap) { var asset = ScriptableObject.CreateInstance(); uiMap = new InputActionMap("UI"); + uiMap.AddAction("Point", InputActionType.PassThrough, "/position"); asset.AddActionMap(uiMap); return asset; } From 15e20a1b4a1ace93fc281bbac07d01edf6526481 Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Thu, 28 May 2026 10:50:35 +0530 Subject: [PATCH 13/15] Clearing the callback in teardown to avoid test pollution. --- Assets/Tests/InputSystem/Plugins/InputForUITests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index 128189f41b..316db2dfb3 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -65,6 +65,8 @@ public override void TearDown() EventProvider.ClearMockProvider(); m_InputForUIEvents.Clear(); + InputSystemProvider.SetOnRegisterActions(null); + // InputSystem.actions setter throws in play mode, so we use the internal manager property here. InputSystem.manager.actions = storedActions; From 3775eb77a58c7b6b7b6f74495d20b47eeddff5a6 Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Thu, 28 May 2026 18:56:11 +0530 Subject: [PATCH 14/15] The teardown cleanup is unnecessary. --- Assets/Tests/InputSystem/Plugins/InputForUITests.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index 316db2dfb3..128189f41b 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -65,8 +65,6 @@ public override void TearDown() EventProvider.ClearMockProvider(); m_InputForUIEvents.Clear(); - InputSystemProvider.SetOnRegisterActions(null); - // InputSystem.actions setter throws in play mode, so we use the internal manager property here. InputSystem.manager.actions = storedActions; From 1478b5b593147b4dee08df9cfb6c4c94ab22ae28 Mon Sep 17 00:00:00 2001 From: Aswin Gopal Date: Fri, 29 May 2026 10:47:16 +0530 Subject: [PATCH 15/15] Use OnActionsChange() instead of Initialize() to re-select action asset in tests. --- Assets/Tests/InputSystem/Plugins/InputForUITests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs index 128189f41b..98720c0ee4 100644 --- a/Assets/Tests/InputSystem/Plugins/InputForUITests.cs +++ b/Assets/Tests/InputSystem/Plugins/InputForUITests.cs @@ -124,7 +124,7 @@ public void Shutdown_DoesNotDisableProjectWideActionsAsset() InputSystem.manager.actions = asset; try { - m_InputSystemProvider.Initialize(); + m_InputSystemProvider.OnActionsChange(); Assert.That(uiMap.enabled, Is.True, "UI action map should be enabled by provider initialization."); Assert.That(gameplayMap.enabled, Is.True, "Provider must not change enabled state of non-UI maps."); @@ -151,7 +151,7 @@ public void Shutdown_DoesNotDisableProjectWideUIMap_WhenAlreadyEnabledBeforeInit InputSystem.manager.actions = asset; try { - m_InputSystemProvider.Initialize(); + m_InputSystemProvider.OnActionsChange(); Assert.That(uiMap.enabled, Is.True, "UI action map should remain enabled after provider initialization."); EventProvider.ClearMockProvider(); @@ -177,7 +177,7 @@ public void Shutdown_DisablesUIActionMap_ForProviderOwnedAsset() // Remove project-wide actions so the provider falls back to its own internal default asset. // InputSystem.actions setter throws in play mode, so we use the internal manager property here. InputSystem.manager.actions = null; - m_InputSystemProvider.Initialize(); + m_InputSystemProvider.OnActionsChange(); InputSystemProvider.SetOnRegisterActions(null); Assert.That(capturedUIMap, Is.Not.Null, "Provider should have a UI action map in its internal default asset.");