Skip to content

Commit 35f8b70

Browse files
ekcohK-Tone
andauthored
FIX: ISXB-1306 Fixed a bug within InputActionAsset.cs that prevented actions containing slashes to be found by name. (#2160)
Co-authored-by: Anthony Yakovlev <anthony.yakovlev@gmail.com>
1 parent d93d150 commit 35f8b70

File tree

3 files changed

+58
-22
lines changed

3 files changed

+58
-22
lines changed

Assets/Tests/InputSystem/CoreTests_Actions.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4939,6 +4939,7 @@ public void Actions_CanLookUpActionInMap()
49394939

49404940
var action1 = map.AddAction("action1");
49414941
var action2 = map.AddAction("action2");
4942+
var yawPitch = map.AddAction("Yaw/Pitch");
49424943

49434944
Assert.That(map.FindAction("action1"), Is.SameAs(action1));
49444945
Assert.That(map.FindAction("action2"), Is.SameAs(action2));
@@ -4947,6 +4948,10 @@ public void Actions_CanLookUpActionInMap()
49474948
// Lookup is case-insensitive.
49484949
Assert.That(map.FindAction("Action1"), Is.SameAs(action1));
49494950
Assert.That(map.FindAction("Action2"), Is.SameAs(action2));
4951+
4952+
// Lookup allows '/' within action name (https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1306)
4953+
// yawPitchAction = _actions.FindAction("Yaw/Pitch");
4954+
Assert.That(map.FindAction("Yaw/Pitch"), Is.SameAs(yawPitch));
49504955
}
49514956

49524957
[Test]
@@ -8106,6 +8111,7 @@ public void Actions_CanLookUpActionInAssetByName()
81068111
var action1 = map1.AddAction("action1");
81078112
var action2 = map1.AddAction("action2");
81088113
var action3 = map2.AddAction("action3");
8114+
var action4 = map2.AddAction("Yaw/Pitch");
81098115

81108116
Assert.That(asset.FindAction("action1"), Is.SameAs(action1));
81118117
Assert.That(asset.FindAction("action2"), Is.SameAs(action2));
@@ -8119,6 +8125,10 @@ public void Actions_CanLookUpActionInAssetByName()
81198125
Assert.That(asset.FindAction($"{{{action2.id.ToString()}}}"), Is.SameAs(action2));
81208126
Assert.That(asset.FindAction($"{{{action3.id.ToString()}}}"), Is.SameAs(action3));
81218127

8128+
// Lookup allows '/' within action name (https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1306)
8129+
// yawPitchAction = _actions.FindAction("Yaw/Pitch");
8130+
Assert.That(asset.FindAction("Yaw/Pitch"), Is.SameAs(action4));
8131+
81228132
// Shouldn't allocate.
81238133
var map1action1 = "map1/action1";
81248134
Assert.That(() =>
@@ -8127,6 +8137,26 @@ public void Actions_CanLookUpActionInAssetByName()
81278137
}, Is.Not.AllocatingGCMemory());
81288138
}
81298139

8140+
[Test]
8141+
[Category("Actions")]
8142+
[Description("See https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1306")]
8143+
public void Actions_CanLookUpActionInAssetByNameIfHavingActionAndMapActionWithSameName()
8144+
{
8145+
var asset = ScriptableObject.CreateInstance<InputActionAsset>();
8146+
8147+
var map1 = new InputActionMap("map1");
8148+
var map2 = new InputActionMap("Yaw");
8149+
8150+
asset.AddActionMap(map1);
8151+
asset.AddActionMap(map2);
8152+
8153+
var action1 = map1.AddAction("Yaw/Pitch");
8154+
var action2 = map2.AddAction("Pitch");
8155+
8156+
// map/action should be selected first
8157+
Assert.That(asset.FindAction("Yaw/Pitch"), Is.SameAs(action2));
8158+
}
8159+
81308160
// Since we allow looking up by action name without any map qualification, ambiguities result when several
81318161
// actions are named the same. We choose to not do anything special other than generally preferring an
81328162
// enabled action over a disabled one. Other than that, we just return the first hit.

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ however, it has to be formatted properly to pass verification tests.
1818
- Fixed an issue on macOS which didn't detect up-left DPAD presses for Xbox controllers. [ISXB-810](https://issuetracker.unity3d.com/issues/macos-d-pad-upper-left-corner-is-not-logged-with-the-xbox-controller)
1919
- Fixed Input Actions code generation overwriting user files when the names happened to match. [ISXB-1257](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1257)
2020
- Fixed an issue when providing JoinPlayer with a specific split screen index. [ISXB-897](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-897)
21+
- Fixed an issue where an action with a name containing a slash "/" could not be found via `InputActionAsset.FindAction(string,bool)`. [ISXB-1306](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1306).
2122

2223
## [1.14.0] - 2025-03-20
2324

Packages/com.unity.inputsystem/InputSystem/Actions/InputActionAsset.cs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ public static InputActionAsset FromJson(string json)
471471
/// in the asset.
472472
/// </summary>
473473
/// <param name="actionNameOrId">Name of the action as either a "map/action" combination (e.g. "gameplay/fire") or
474-
/// a simple name. In the former case, the name is split at the '/' slash and the first part is used to find
474+
/// a simple name (e.g. "fire"). In the former case, the name is split at the '/' slash and the first part is used to find
475475
/// a map with that name and the second part is used to find an action with that name inside the map. In the
476476
/// latter case, all maps are searched in order and the first action that has the given name in any of the maps
477477
/// is returned. Note that name comparisons are case-insensitive.
@@ -491,6 +491,10 @@ public static InputActionAsset FromJson(string json)
491491
/// An exception is if, of the multiple actions with the same name, some are enabled and some are disabled. In
492492
/// this case, the first action that is enabled is returned.
493493
///
494+
/// If an action name contains a slash "/", e.g. "yaw/pitch" and there is also a map called "yaw" which
495+
/// contains an action "pitch", the action "pitch" within the map "yaw" will be returned instead of the
496+
/// action named "yaw/pitch".
497+
///
494498
/// <example>
495499
/// <code>
496500
/// var asset = ScriptableObject.CreateInstance&lt;InputActionAsset&gt;();
@@ -533,28 +537,11 @@ public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = fals
533537

534538
if (m_ActionMaps != null)
535539
{
536-
// Check if we have a "map/action" path.
540+
// Check if we have a "map/action" path. If we do we either has a "map/action" path or a simple
541+
// action name containing a slash. We first attempt matching it to a "map/action" and only if that
542+
// fails do we attempt to search for a "some/action" name.
537543
var indexOfSlash = actionNameOrId.IndexOf('/');
538-
if (indexOfSlash == -1)
539-
{
540-
// No slash so it's just a simple action name. Return either first enabled action or, if
541-
// none are enabled, first action with the given name.
542-
InputAction firstActionFound = null;
543-
for (var i = 0; i < m_ActionMaps.Length; ++i)
544-
{
545-
var action = m_ActionMaps[i].FindAction(actionNameOrId);
546-
if (action != null)
547-
{
548-
if (action.enabled || action.m_Id == actionNameOrId) // Match by ID is always exact.
549-
return action;
550-
if (firstActionFound == null)
551-
firstActionFound = action;
552-
}
553-
}
554-
if (firstActionFound != null)
555-
return firstActionFound;
556-
}
557-
else
544+
if (indexOfSlash >= 0)
558545
{
559546
// Have a path. First search for the map, then for the action.
560547
var mapName = new Substring(actionNameOrId, 0, indexOfSlash);
@@ -583,6 +570,24 @@ public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = fals
583570
break;
584571
}
585572
}
573+
574+
// Check if there is an action with the given name regardless of containing map.
575+
// If multiple actions exist with the same identifier, the first enabled one is returned.
576+
// If no enabled action exist, the first is returned.
577+
InputAction firstActionFound = null;
578+
for (var i = 0; i < m_ActionMaps.Length; ++i)
579+
{
580+
var action = m_ActionMaps[i].FindAction(actionNameOrId);
581+
if (action != null)
582+
{
583+
if (action.enabled || action.m_Id == actionNameOrId) // Match by ID is always exact.
584+
return action;
585+
if (firstActionFound == null)
586+
firstActionFound = action;
587+
}
588+
}
589+
if (firstActionFound != null)
590+
return firstActionFound;
586591
}
587592

588593
if (throwIfNotFound)

0 commit comments

Comments
 (0)