Skip to content
75 changes: 75 additions & 0 deletions Assets/Tests/InputSystem/Plugins/UITests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2764,6 +2764,81 @@ public void UI_ClickDraggingMouseDoesNotAllocateGCMemory()
}, Is.Not.AllocatingGCMemory());
}

[UnityTest]
[Category("UI")]
public IEnumerator UI_CanNavigateUI_WithLocalMultiPlayerRoot_Null_UsingGamepads()
{
// Setup navigation
var gamepad = InputSystem.AddDevice<Gamepad>();
var scene = CreateTestUI(makeSelectable: true);

// Create actions for navigation
var asset = ScriptableObject.CreateInstance<InputActionAsset>();
var map = asset.AddActionMap("map");
var moveAction = map.AddAction("move", type: InputActionType.Value, binding: "<Gamepad>/leftStick");
var submitAction = map.AddAction("submit", type: InputActionType.Button, binding: "<Gamepad>/buttonSouth");

// Assign actions to the UI module
scene.uiModule.move = InputActionReference.Create(moveAction);
scene.uiModule.submit = InputActionReference.Create(submitAction);
map.Enable();

// Test 1: Assign localMultiPlayerRoot to a value
scene.eventSystem.playerRoot = scene.parentGameObject;

// Initial selection
scene.eventSystem.SetSelectedGameObject(scene.leftGameObject);
yield return null;

// Move right
Set(gamepad.leftStick, new Vector2(1, 0));
yield return null;

Assert.That(scene.eventSystem.currentSelectedGameObject, Is.SameAs(scene.rightGameObject), "Right navigation did not work when localMultiPlayerRoot was set");

// Move left
Set(gamepad.leftStick, Vector2.zero);
yield return null;
Set(gamepad.leftStick, new Vector2(-1, 0));
yield return null;

Assert.That(scene.eventSystem.currentSelectedGameObject, Is.SameAs(scene.leftGameObject), "Left navigation did not work when localMultiPlayerRoot was set");

// Reset stick position
Set(gamepad.leftStick, Vector2.zero);
yield return null;

// Test 2: With localMultiPlayerRoot set to null
scene.eventSystem.playerRoot = null;

// Reset selection
scene.eventSystem.SetSelectedGameObject(scene.leftGameObject);
yield return null;

// Move right
Set(gamepad.leftStick, new Vector2(1, 0));
yield return null;

Assert.That(scene.eventSystem.currentSelectedGameObject, Is.SameAs(scene.rightGameObject), "Right navigation did not work when localMultiPlayerRoot was null");

// Move left
Set(gamepad.leftStick, Vector2.zero);
yield return null;
Set(gamepad.leftStick, new Vector2(-1, 0));
yield return null;

Assert.That(scene.eventSystem.currentSelectedGameObject, Is.SameAs(scene.leftGameObject), "Left navigation did not work when localMultiPlayerRoot was null");

// Submit
PressAndRelease(gamepad.buttonSouth);
yield return null;

Assert.That(scene.leftChildReceiver.events, Has.Exactly(1).With.Property("type").EqualTo(EventType.Submit), "Submit event was not received when localMultiPlayerRoot was null");

// Checking that localMultiPlayerRoot is null
Assert.AreEqual(null, scene.uiModule.localMultiPlayerRoot);
}

[UnityTest]
[Category("UI")]
// Check that two players can have separate UI, and that both selections will stay active when
Expand Down
1 change: 1 addition & 0 deletions Packages/com.unity.inputsystem/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ however, it has to be formatted properly to pass verification tests.
- Fixed an issue in `RebindingUISample` preventing UI navigation without Keyboard and Mouse present.
- Fixed an issue in `RebindActionUI` which resulted in active binding not being shown after a scene reload. ISXB-1588.
- Fixed an issue in `GamepadIconExample` which resulted in icons for left and right triggers not being displayed after a rebind to the exact same controls. ISXB-1593.
- Fixed an issue where `InputSystemUIInputModule.localMultiPlayerRoot` could not be set to `null` when using `MultiplayerEventSystem`. [ISXB-1610](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1610)

## [1.14.2] - 2025-08-05

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ protected override void OnDisable()

private void InitializePlayerRoot()
{
if (m_PlayerRoot == null) return;

var inputModule = GetComponent<InputSystemUIInputModule>();
if (inputModule != null)
inputModule.localMultiPlayerRoot = m_PlayerRoot;
Expand Down