Skip to content

Commit 71f445c

Browse files
authored
FIX: Ensure callback delegates are created for ActionMaps added after an asset has already assigned to PlayerInput component (case ISXB-711) (#2077)
1 parent ed159b5 commit 71f445c

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

Assets/Tests/InputSystem/Plugins/PlayerInputTests.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2405,6 +2405,39 @@ public void PlayerInput_CanDisableAfterAssigningAction_WithControlSchemesAndInte
24052405
player.SetActive(false); // Should cause full rebinding and not assert
24062406
}
24072407

2408+
[Test]
2409+
[Category("PlayerInput")]
2410+
public void PlayerInput_DelegatesAreUpdate_WhenActionMapAddedAfterAssignment()
2411+
{
2412+
var gamepad = InputSystem.AddDevice<Gamepad>();
2413+
2414+
var go = new GameObject();
2415+
var listener = go.AddComponent<MessageListener>();
2416+
var playerInput = go.AddComponent<PlayerInput>();
2417+
playerInput.defaultActionMap = "Other";
2418+
var actionAsset = InputActionAsset.FromJson(kActions);
2419+
playerInput.actions = actionAsset;
2420+
2421+
// Disable the asset while adding another action map to it as none
2422+
// of the actions in the asset can be enabled during modification
2423+
//
2424+
actionAsset.Disable();
2425+
var keyboard = InputSystem.AddDevice<Keyboard>();
2426+
var newActionMap = actionAsset.AddActionMap("NewMap");
2427+
var newAction = newActionMap.AddAction("NewAction");
2428+
newAction.AddBinding("<Keyboard>/k", groups: "Keyboard");
2429+
actionAsset.AddControlScheme("Keyboard").WithRequiredDevice<Keyboard>();
2430+
actionAsset.Enable();
2431+
2432+
playerInput.currentActionMap = newActionMap;
2433+
playerInput.ActivateInput();
2434+
listener.messages.Clear();
2435+
2436+
Press(keyboard.kKey);
2437+
2438+
Assert.That(listener.messages, Has.Exactly(1).With.Property("name").EqualTo("OnNewAction"));
2439+
}
2440+
24082441
private struct Message : IEquatable<Message>
24092442
{
24102443
public string name { get; set; }
@@ -2477,6 +2510,11 @@ public void OnOtherAction(InputValue value)
24772510
messages?.Add(new Message { name = "OnOtherAction", value = value.Get<float>() });
24782511
}
24792512

2513+
public void OnNewAction(InputValue value)
2514+
{
2515+
messages?.Add(new Message { name = "OnNewAction", value = value.Get<float>() });
2516+
}
2517+
24802518
// ReSharper disable once UnusedMember.Local
24812519
public void OnActionWithSpaces(InputValue value)
24822520
{

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ however, it has to be formatted properly to pass verification tests.
3232
- Fixed an issue in `Samples/Visualizers/GamepadVisualizer.unity` sample where the visualization wouldn't handle device disconnects or current device changes properly (ISXB-1243).
3333
- Fixed an issue when displaying Serialized InputAction's Processor properties inside the Inspector window. [ISXB-1269](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1269)
3434
- Fixed an issue with default device selection when adding new Control Scheme.
35+
- Fixed an issue where action map delegates were not updated when the asset already assigned to the PlayerInput component were changed [ISXB-711](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-711).
3536

3637
### Changed
3738
- Added back the InputManager to InputSystem project-wide asset migration code with performance improvement (ISX-2086).

Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/PlayerInput.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,8 @@ public TDevice GetDevice<TDevice>()
950950
/// </example>
951951
public void ActivateInput()
952952
{
953+
UpdateDelegates();
954+
953955
m_InputActive = true;
954956

955957
// If we have no current action map but there's a default
@@ -960,6 +962,31 @@ public void ActivateInput()
960962
m_CurrentActionMap?.Enable();
961963
}
962964

965+
// Users can add and remove actions maps *after* assigning an InputActionAsset to the PlayerInput component.
966+
// This ensures "actionTriggered" delegates are assigned for new maps (case isxb-711)
967+
//
968+
private int m_AllMapsHashCode = 0;
969+
private void UpdateDelegates()
970+
{
971+
if (m_Actions == null)
972+
{
973+
m_AllMapsHashCode = 0;
974+
return;
975+
}
976+
977+
int allMapsHashCode = 0;
978+
foreach (var actionMap in m_Actions.actionMaps)
979+
{
980+
allMapsHashCode ^= actionMap.GetHashCode();
981+
}
982+
if (m_AllMapsHashCode != allMapsHashCode)
983+
{
984+
InstallOnActionTriggeredHook();
985+
CacheMessageNames();
986+
m_AllMapsHashCode = allMapsHashCode;
987+
}
988+
}
989+
963990
/// <summary>
964991
/// Disable input on the player, by disabling the current action map
965992
/// </summary>
@@ -1515,6 +1542,8 @@ private void CacheMessageNames()
15151542

15161543
private void ClearCaches()
15171544
{
1545+
if (m_ActionMessageNames != null)
1546+
m_ActionMessageNames.Clear();
15181547
}
15191548

15201549
/// <summary>

0 commit comments

Comments
 (0)