From 314de29ba7caa9b583754d2746d8513fe6306bab Mon Sep 17 00:00:00 2001 From: Anthony Yakovlev Date: Mon, 8 Jun 2026 18:28:04 +0300 Subject: [PATCH 1/6] add the first set of genre-based tests - rts-related ones --- .../CoreTests_ActionPriority_Genres.cs | 104 ++++++++++++++++++ .../CoreTests_ActionPriority_Genres.cs.meta | 11 ++ 2 files changed, 115 insertions(+) create mode 100644 Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs create mode 100644 Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs.meta diff --git a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs new file mode 100644 index 0000000000..91a0f2ca73 --- /dev/null +++ b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs @@ -0,0 +1,104 @@ +using NUnit.Framework; +using UnityEngine.InputSystem; +using UnityEngine.InputSystem.Controls; + +/// +/// Genre-style shortcut examples (RTS, shooter, etc.) migrated from sample projects into the Input System test suite. +/// +internal partial class CoreTests +{ + /// + /// Programmatic map matching the RTS example scene: plain 1, Shift+1, and Ctrl+Shift+1 on the same binding key. + /// + private static InputActionMap CreateRtsExampleShortcutMap( + out InputAction actionOne, + out InputAction actionShiftOne, + out InputAction actionControlShiftOne) + { + var map = new InputActionMap("RTSShortcuts"); + + actionOne = map.AddAction("One", InputActionType.Button); + actionOne.AddBinding("/1"); + + actionShiftOne = map.AddAction("ShiftOne", InputActionType.Button); + actionShiftOne.AddCompositeBinding("OneModifier") + .With("modifier", "/shift") + .With("binding", "/1"); + actionShiftOne.Priority = 1; + + actionControlShiftOne = map.AddAction("ControlShiftOne", InputActionType.Button); + actionControlShiftOne.AddCompositeBinding("TwoModifiers") + .With("modifier1", "/ctrl") + .With("modifier2", "/shift") + .With("binding", "/1"); + actionControlShiftOne.Priority = 2; + + return map; + } + + [Test] + [Category("Actions Priority")] + public void Actions_Priority_Genres_RTS_Key1Only_ActivatesPlainOne() + { + EnableComplexityShortcutResolution(); + var keyboard = InputSystem.AddDevice(); + using var map = CreateRtsExampleShortcutMap(out var actionOne, out var actionShiftOne, out var actionControlShiftOne); + map.Enable(); + + Press((ButtonControl)keyboard.digit1Key); + InputSystem.Update(); + + Assert.That(actionOne.IsPressed(), Is.True); + Assert.That(actionShiftOne.IsPressed(), Is.False); + Assert.That(actionControlShiftOne.IsPressed(), Is.False); + + Release((ButtonControl)keyboard.digit1Key); + InputSystem.Update(); + } + + [Test] + [Category("Actions Priority")] + public void Actions_Priority_Genres_RTS_ShiftOne_SuppressesPlainOne() + { + EnableComplexityShortcutResolution(); + var keyboard = InputSystem.AddDevice(); + using var map = CreateRtsExampleShortcutMap(out var actionOne, out var actionShiftOne, out var actionControlShiftOne); + map.Enable(); + + Press((ButtonControl)keyboard.shiftKey); + Press((ButtonControl)keyboard.digit1Key); + InputSystem.Update(); + + Assert.That(actionOne.IsPressed(), Is.False, "Plain 1 should not activate when Shift+1 wins."); + Assert.That(actionShiftOne.IsPressed(), Is.True, "Shift+1 should activate."); + Assert.That(actionControlShiftOne.IsPressed(), Is.False); + + Release((ButtonControl)keyboard.digit1Key); + Release((ButtonControl)keyboard.shiftKey); + InputSystem.Update(); + } + + [Test] + [Category("Actions Priority")] + public void Actions_Priority_Genres_RTS_ControlShiftOne_SuppressesLowerTiers() + { + EnableComplexityShortcutResolution(); + var keyboard = InputSystem.AddDevice(); + using var map = CreateRtsExampleShortcutMap(out var actionOne, out var actionShiftOne, out var actionControlShiftOne); + map.Enable(); + + Press((ButtonControl)keyboard.ctrlKey); + Press((ButtonControl)keyboard.shiftKey); + Press((ButtonControl)keyboard.digit1Key); + InputSystem.Update(); + + Assert.That(actionOne.IsPressed(), Is.False, "Plain 1 should not activate when Ctrl+Shift+1 wins."); + Assert.That(actionShiftOne.IsPressed(), Is.False, "Shift+1 should not activate when Ctrl+Shift+1 wins."); + Assert.That(actionControlShiftOne.IsPressed(), Is.True, "Ctrl+Shift+1 should activate."); + + Release((ButtonControl)keyboard.digit1Key); + Release((ButtonControl)keyboard.shiftKey); + Release((ButtonControl)keyboard.ctrlKey); + InputSystem.Update(); + } +} diff --git a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs.meta b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs.meta new file mode 100644 index 0000000000..d73fa8ebaf --- /dev/null +++ b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e4f2a1b9c3d4e5f6a7b8c9d0e1f2a3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 01546723e063b65eac37b1ab13652d1310664059 Mon Sep 17 00:00:00 2001 From: Anthony Yakovlev Date: Mon, 8 Jun 2026 19:43:07 +0300 Subject: [PATCH 2/6] add joystick tests --- .../CoreTests_ActionPriority_Genres.cs | 109 +++++++++++++++++- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs index 91a0f2ca73..34bf7ac4a2 100644 --- a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs +++ b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs @@ -1,4 +1,5 @@ using NUnit.Framework; +using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; @@ -8,7 +9,7 @@ internal partial class CoreTests { /// - /// Programmatic map matching the RTS example scene: plain 1, Shift+1, and Ctrl+Shift+1 on the same binding key. + /// Here we have some RTS-related actions and tests. This whole thing emerged out of having to implement control groups in RTS games. /// private static InputActionMap CreateRtsExampleShortcutMap( out InputAction actionOne, @@ -40,7 +41,8 @@ private static InputActionMap CreateRtsExampleShortcutMap( [Category("Actions Priority")] public void Actions_Priority_Genres_RTS_Key1Only_ActivatesPlainOne() { - EnableComplexityShortcutResolution(); + EnableActionPriorityShortcutResolution(); + var keyboard = InputSystem.AddDevice(); using var map = CreateRtsExampleShortcutMap(out var actionOne, out var actionShiftOne, out var actionControlShiftOne); map.Enable(); @@ -60,7 +62,8 @@ public void Actions_Priority_Genres_RTS_Key1Only_ActivatesPlainOne() [Category("Actions Priority")] public void Actions_Priority_Genres_RTS_ShiftOne_SuppressesPlainOne() { - EnableComplexityShortcutResolution(); + EnableActionPriorityShortcutResolution(); + var keyboard = InputSystem.AddDevice(); using var map = CreateRtsExampleShortcutMap(out var actionOne, out var actionShiftOne, out var actionControlShiftOne); map.Enable(); @@ -82,7 +85,8 @@ public void Actions_Priority_Genres_RTS_ShiftOne_SuppressesPlainOne() [Category("Actions Priority")] public void Actions_Priority_Genres_RTS_ControlShiftOne_SuppressesLowerTiers() { - EnableComplexityShortcutResolution(); + EnableActionPriorityShortcutResolution(); + var keyboard = InputSystem.AddDevice(); using var map = CreateRtsExampleShortcutMap(out var actionOne, out var actionShiftOne, out var actionControlShiftOne); map.Enable(); @@ -101,4 +105,101 @@ public void Actions_Priority_Genres_RTS_ControlShiftOne_SuppressesLowerTiers() Release((ButtonControl)keyboard.ctrlKey); InputSystem.Update(); } + + /// + /// The following section emerged from trying input shortcuts with some generic joystick-controlled games, platformer/scroller style. + /// In those games, the move action overlaps with a plenty of special abilities. + /// + private static InputActionMap CreateGenericJoystickExampleShortcutMap( + out InputAction actionMove, + out InputAction actionJump, + out InputAction actionJumpKick) + { + var map = new InputActionMap("DualshockExample"); + + actionMove = map.AddAction("Move", InputActionType.Value, expectedControlLayout: "Vector2"); + actionMove.AddBinding("/leftStick"); + + actionJump = map.AddAction("Jump", InputActionType.Button); + actionJump.AddBinding("/buttonSouth"); + + actionJumpKick = map.AddAction("Jump Kick", InputActionType.Button); + + actionJumpKick.AddCompositeBinding("OneModifier") + .With("modifier", "/leftShoulder") + .With("binding", "/buttonSouth"); + + actionJumpKick.Priority = 1; + + return map; + } + + [Test] + [Category("Actions Priority")] + public void Actions_Priority_Genres_GenericJoystick_LeftStick_Activates_JustOneAction() + { + EnableActionPriorityShortcutResolution(); + + var gamepad = InputSystem.AddDevice(); + using var map = CreateGenericJoystickExampleShortcutMap(out var actionMove, out var actionJump, out var actionJumpKick); + map.Enable(); + + Set(gamepad.leftStick, Vector2.up); + + InputSystem.Update(); + + Assert.IsTrue(actionMove.IsPressed(), "Move should be active when the left stick is tilted."); + Assert.IsFalse(actionJump.IsPressed(), "Jump should not be active without X (south)."); + Assert.IsFalse(actionJumpKick.IsPressed(), "Jump Kick should not be active without L1+X."); + + Set(gamepad.leftStick, Vector2.zero); + InputSystem.Update(); + } + + [Test] + [Category("Actions Priority")] + public void Actions_Priority_Genres_GenericJoystick_LeftStickAndX_Triggers_Move_And_Jump() + { + EnableActionPriorityShortcutResolution(); + + var gamepad = InputSystem.AddDevice(); + using var map = CreateGenericJoystickExampleShortcutMap(out var actionMove, out var actionJump, out var actionJumpKick); + map.Enable(); + + Set(gamepad.leftStick, Vector2.up); + Press(gamepad.buttonSouth); + + InputSystem.Update(); + + Assert.IsTrue(actionMove.IsPressed(), "Move should still be active while the stick is tilted."); + Assert.IsTrue(actionJump.IsPressed(), "Jump should be active when X (south) is pressed."); + Assert.IsFalse(actionJumpKick.IsPressed(), "Jump Kick should not be active without L1."); + + Release(gamepad.buttonSouth); + Set(gamepad.leftStick, Vector2.zero); + InputSystem.Update(); + } + + [Test] + [Category("Actions Priority")] + public void Actions_Priority_Genres_GenericJoystick_L1AndX_Only_Triggers_JumpKick() + { + EnableActionPriorityShortcutResolution(); + + var gamepad = InputSystem.AddDevice(); + using var map = CreateGenericJoystickExampleShortcutMap(out var actionMove, out var actionJump, out var actionJumpKick); + map.Enable(); + + Press(gamepad.leftShoulder); + Press(gamepad.buttonSouth); + + InputSystem.Update(); + + Assert.IsFalse(actionMove.IsPressed(), "Move should not be active when the stick is neutral."); + Assert.IsFalse(actionJump.IsPressed(), "Jump should not consume when Jump Kick wins (priority + consume)."); + Assert.IsTrue(actionJumpKick.IsPressed(), "Jump Kick should be active for L1+X."); + + Release(gamepad.buttonSouth); + Release(gamepad.leftShoulder); + } } From 5e5a23f5c832964d5067410f6d3feeb40fba34f6 Mon Sep 17 00:00:00 2001 From: Anthony Yakovlev Date: Mon, 8 Jun 2026 19:57:50 +0300 Subject: [PATCH 3/6] move shooter examples as well --- .../CoreTests_ActionPriority_Genres.cs | 107 +++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs index 34bf7ac4a2..1a09a6448f 100644 --- a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs +++ b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs @@ -115,7 +115,7 @@ private static InputActionMap CreateGenericJoystickExampleShortcutMap( out InputAction actionJump, out InputAction actionJumpKick) { - var map = new InputActionMap("DualshockExample"); + var map = new InputActionMap("JoystickExample"); actionMove = map.AddAction("Move", InputActionType.Value, expectedControlLayout: "Vector2"); actionMove.AddBinding("/leftStick"); @@ -202,4 +202,109 @@ public void Actions_Priority_Genres_GenericJoystick_L1AndX_Only_Triggers_JumpKic Release(gamepad.buttonSouth); Release(gamepad.leftShoulder); } + + /// + /// The following section originates from shooter games where move overlaps with a bunch of weapon controls and team interactions. + /// + private static InputActionMap CreateShooterExampleShortcutMap( + out InputAction actionMove, + out InputAction actionRunFast, + out InputAction actionTeamChat) + { + + var map = new InputActionMap("ShooterExample"); + + actionMove = map.AddAction("Move", InputActionType.Value); + actionMove.AddCompositeBinding("2DVector") + .With("up", "/w") + .With("down", "/s") + .With("left", "/a") + .With("right", "/d"); + + actionRunFast = map.AddAction("Run Fast", InputActionType.Button); + actionRunFast.AddCompositeBinding("OneModifier") + .With("modifier", "/shift") + .With("binding", "/w"); + + actionTeamChat = map.AddAction("Team chat", InputActionType.Button); + actionTeamChat.AddCompositeBinding("TwoModifiers") + .With("modifier1", "/alt") + .With("modifier2", "/shift") + .With("binding", "/w"); + + actionTeamChat.Priority = 2; + + return map; + } + + [Test] + [Category("Actions Priority")] + public void Actions_Priority_Genres_Shooter_Move_Only_Triggers_Move() + { + EnableActionPriorityShortcutResolution(); + var keyboard = InputSystem.AddDevice(); + using var map = CreateShooterExampleShortcutMap(out var actionMove, out var actionRunFast, out var actionTeamChat); + map.Enable(); + + Press(keyboard.wKey); + InputSystem.Update(); + + Assert.IsTrue(actionMove.IsPressed(), "Move should be activated by W."); + Assert.IsFalse(actionRunFast.IsPressed(), "Run Fast should not be activated by W alone."); + Assert.IsFalse(actionTeamChat.IsPressed(), "Team chat should not be activated by W alone."); + + Release(keyboard.wKey); + InputSystem.Update(); + } + + [Test] + [Category("Actions Priority")] + public void Actions_Priority_Genres_Shooter_ShiftW_Triggers_Move_And_RunFast() + { + EnableActionPriorityShortcutResolution(); + var keyboard = InputSystem.AddDevice(); + using var map = CreateShooterExampleShortcutMap(out var actionMove, out var actionRunFast, out var actionTeamChat); + map.Enable(); + + Press(keyboard.leftShiftKey); + Press(keyboard.wKey); + + InputSystem.Update(); + + Assert.IsTrue(actionMove.IsPressed(), "Move should still be activated by W."); + Assert.IsTrue(actionRunFast.IsPressed(), "Run Fast should be activated by Shift+W."); + Assert.IsFalse(actionTeamChat.IsPressed(), "Team chat should not be activated without Alt."); + + Release(keyboard.wKey); + Release(keyboard.leftShiftKey); + InputSystem.Update(); + } + + [Test] + [Category("Actions Priority")] + public void Actions_Priority_Genres_Shooter_AltShiftW_Only_Triggers_TeamChat() + { + EnableActionPriorityShortcutResolution(); + var keyboard = InputSystem.AddDevice(); + using var map = CreateShooterExampleShortcutMap(out var actionMove, out var actionRunFast, out var actionTeamChat); + map.Enable(); + + Press(keyboard.leftAltKey); + Press(keyboard.leftShiftKey); + Press(keyboard.wKey); + + InputSystem.Update(); + + Assert.IsTrue( + actionTeamChat.IsPressed() || actionTeamChat.IsInProgress(), + "Team chat should trigger when Alt, Shift, and W are down together."); + + Assert.IsFalse(actionMove.IsPressed(), "Move shouldn't be activated!"); + + Release(keyboard.leftAltKey); + Release(keyboard.leftShiftKey); + Release(keyboard.wKey); + + InputSystem.Update(); + } } From 638a586f30ec9a2948b6c55db5446bd1f4c64194 Mon Sep 17 00:00:00 2001 From: Anthony Yakovlev Date: Mon, 8 Jun 2026 19:59:11 +0300 Subject: [PATCH 4/6] code formatting --- .../InputSystem/CoreTests_ActionPriority_Genres.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs index 1a09a6448f..4990bc0a03 100644 --- a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs +++ b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs @@ -86,7 +86,7 @@ public void Actions_Priority_Genres_RTS_ShiftOne_SuppressesPlainOne() public void Actions_Priority_Genres_RTS_ControlShiftOne_SuppressesLowerTiers() { EnableActionPriorityShortcutResolution(); - + var keyboard = InputSystem.AddDevice(); using var map = CreateRtsExampleShortcutMap(out var actionOne, out var actionShiftOne, out var actionControlShiftOne); map.Enable(); @@ -124,7 +124,7 @@ private static InputActionMap CreateGenericJoystickExampleShortcutMap( actionJump.AddBinding("/buttonSouth"); actionJumpKick = map.AddAction("Jump Kick", InputActionType.Button); - + actionJumpKick.AddCompositeBinding("OneModifier") .With("modifier", "/leftShoulder") .With("binding", "/buttonSouth"); @@ -153,7 +153,7 @@ public void Actions_Priority_Genres_GenericJoystick_LeftStick_Activates_JustOneA Assert.IsFalse(actionJumpKick.IsPressed(), "Jump Kick should not be active without L1+X."); Set(gamepad.leftStick, Vector2.zero); - InputSystem.Update(); + InputSystem.Update(); } [Test] @@ -177,7 +177,7 @@ public void Actions_Priority_Genres_GenericJoystick_LeftStickAndX_Triggers_Move_ Release(gamepad.buttonSouth); Set(gamepad.leftStick, Vector2.zero); - InputSystem.Update(); + InputSystem.Update(); } [Test] @@ -211,7 +211,6 @@ private static InputActionMap CreateShooterExampleShortcutMap( out InputAction actionRunFast, out InputAction actionTeamChat) { - var map = new InputActionMap("ShooterExample"); actionMove = map.AddAction("Move", InputActionType.Value); @@ -305,6 +304,6 @@ public void Actions_Priority_Genres_Shooter_AltShiftW_Only_Triggers_TeamChat() Release(keyboard.leftShiftKey); Release(keyboard.wKey); - InputSystem.Update(); + InputSystem.Update(); } } From 43928e78e56046236a51528239c2b5eacd0cf4c5 Mon Sep 17 00:00:00 2001 From: Anthony Yakovlev Date: Mon, 8 Jun 2026 21:32:18 +0300 Subject: [PATCH 5/6] Update Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs Co-authored-by: u-pr[bot] <205906871+u-pr[bot]@users.noreply.github.com> --- Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs index 4990bc0a03..905142b7a5 100644 --- a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs +++ b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs @@ -201,6 +201,7 @@ public void Actions_Priority_Genres_GenericJoystick_L1AndX_Only_Triggers_JumpKic Release(gamepad.buttonSouth); Release(gamepad.leftShoulder); + InputSystem.Update(); } /// From 954bde590b043bbbfc4d4d6c77f6fb09639143f6 Mon Sep 17 00:00:00 2001 From: Anthony Yakovlev Date: Mon, 8 Jun 2026 21:43:42 +0300 Subject: [PATCH 6/6] Update Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs Co-authored-by: u-pr[bot] <205906871+u-pr[bot]@users.noreply.github.com> --- Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs index 905142b7a5..2c580f78fc 100644 --- a/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs +++ b/Assets/Tests/InputSystem/CoreTests_ActionPriority_Genres.cs @@ -300,6 +300,7 @@ public void Actions_Priority_Genres_Shooter_AltShiftW_Only_Triggers_TeamChat() "Team chat should trigger when Alt, Shift, and W are down together."); Assert.IsFalse(actionMove.IsPressed(), "Move shouldn't be activated!"); + Assert.IsFalse(actionRunFast.IsPressed(), "Run Fast shouldn't be activated!"); Release(keyboard.leftAltKey); Release(keyboard.leftShiftKey);