Skip to content

Commit c2dbec3

Browse files
author
Rene Damm
authored
FIX: GC heap garbage from mouse input in UI (#1027).
1 parent 601c5b2 commit c2dbec3

File tree

3 files changed

+139
-95
lines changed

3 files changed

+139
-95
lines changed

Assets/Tests/InputSystem/Plugins/UITests.cs

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
using UnityEngine.InputSystem.LowLevel;
1212
using UnityEngine.InputSystem.UI;
1313
using UnityEngine.InputSystem.Utilities;
14+
using UnityEngine.Profiling;
1415
using UnityEngine.TestTools;
16+
using UnityEngine.TestTools.Constraints;
1517
using UnityEngine.UI;
1618
using TouchPhase = UnityEngine.InputSystem.TouchPhase;
19+
using Is = UnityEngine.TestTools.Constraints.Is;
1720

1821
#pragma warning disable CS0649
1922
////TODO: app focus handling
@@ -113,8 +116,8 @@ private static TestObjects CreateScene(int minY = 0 , int maxY = 480)
113116
}
114117

115118
[UnityTest]
116-
[Category("Actions")]
117-
public IEnumerator Actions_CanDriveUIFromMouse()
119+
[Category("UI")]
120+
public IEnumerator UI_CanDriveUIFromMouse()
118121
{
119122
// Create devices.
120123
var mouse = InputSystem.AddDevice<Mouse>();
@@ -254,8 +257,8 @@ public IEnumerator Actions_CanDriveUIFromMouse()
254257
}
255258

256259
[UnityTest]
257-
[Category("Actions")]
258-
public IEnumerator Actions_TouchActionsCanDriveUIAndDistinguishMultipleTouches()
260+
[Category("UI")]
261+
public IEnumerator UI_TouchActionsCanDriveUIAndDistinguishMultipleTouches()
259262
{
260263
// Create devices.
261264
var touchScreen = InputSystem.AddDevice<Touchscreen>();
@@ -441,10 +444,10 @@ public IEnumerator Actions_TouchActionsCanDriveUIAndDistinguishMultipleTouches()
441444
}
442445

443446
[UnityTest]
444-
[Category("Actions")]
447+
[Category("UI")]
445448
// Check that two players can have separate UI, and that both selections will stay active when
446449
// clicking on UI with the mouse, using MultiPlayerEventSystem.playerRoot to match UI to the players.
447-
public IEnumerator Actions_CanOperateMultiplayerUIGloballyUsingMouse()
450+
public IEnumerator UI_CanOperateMultiplayerUIGloballyUsingMouse()
448451
{
449452
var mouse = InputSystem.AddDevice<Mouse>();
450453

@@ -523,10 +526,10 @@ public IEnumerator Actions_CanOperateMultiplayerUIGloballyUsingMouse()
523526
}
524527

525528
[UnityTest]
526-
[Category("Actions")]
529+
[Category("UI")]
527530
// Check that two players can have separate UI and control it using separate gamepads, using
528531
// MultiplayerEventSystem.
529-
public IEnumerator Actions_CanOperateMultiplayerUILocallyUsingGamepads()
532+
public IEnumerator UI_CanOperateMultiplayerUILocallyUsingGamepads()
530533
{
531534
// Create devices.
532535
var gamepads = new[] { InputSystem.AddDevice<Gamepad>(), InputSystem.AddDevice<Gamepad>() };
@@ -638,8 +641,8 @@ public IEnumerator Actions_CanOperateMultiplayerUILocallyUsingGamepads()
638641
}
639642

640643
[UnityTest]
641-
[Category("Actions")]
642-
public IEnumerator Actions_CanDriveUIFromGamepad()
644+
[Category("UI")]
645+
public IEnumerator UI_CanDriveUIFromGamepad()
643646
{
644647
// Create devices.
645648
var gamepad = InputSystem.AddDevice<Gamepad>();
@@ -741,8 +744,8 @@ public IEnumerator Actions_CanDriveUIFromGamepad()
741744
}
742745

743746
[Test]
744-
[Category("Actions")]
745-
public void Actions_CanReassignUIActions()
747+
[Category("UI")]
748+
public void UI_CanReassignUIActions()
746749
{
747750
var go = new GameObject();
748751
go.AddComponent<EventSystem>();
@@ -789,6 +792,46 @@ public void Actions_CanReassignUIActions()
789792
Assert.That(uiModule.point?.action, Is.Null);
790793
}
791794

795+
[Test]
796+
[Category("UI")]
797+
[Retry(2)] // Warm up JIT
798+
public void UI_MovingAndClickingMouseDoesNotAllocateGCMemory()
799+
{
800+
var mouse = InputSystem.AddDevice<Mouse>();
801+
802+
var actions = ScriptableObject.CreateInstance<InputActionAsset>();
803+
var uiActions = actions.AddActionMap("UI");
804+
var pointAction = uiActions.AddAction("Point", type: InputActionType.PassThrough, binding: "<Mouse>/position");
805+
var clickAction = uiActions.AddAction("Click", type: InputActionType.PassThrough, binding: "<Mouse>/leftButton");
806+
807+
actions.Enable();
808+
809+
var eventSystemGO = new GameObject();
810+
eventSystemGO.AddComponent<EventSystem>();
811+
var uiModule = eventSystemGO.AddComponent<InputSystemUIInputModule>();
812+
uiModule.actionsAsset = actions;
813+
uiModule.point = InputActionReference.Create(pointAction);
814+
uiModule.leftClick = InputActionReference.Create(clickAction);
815+
816+
// We allow the first hit on the UI module to set up internal data structures
817+
// and thus allocate something. So go and run one event with data on the mouse.
818+
// Also gets rid of GC noise from the initial input system update.
819+
InputSystem.QueueStateEvent(mouse, new MouseState { position = new Vector2(1, 2) });
820+
InputSystem.Update();
821+
822+
// Make sure we don't get an allocation from the string literal.
823+
var kProfilerRegion = "UI_MovingAndClickingMouseDoesNotAllocateMemory";
824+
825+
Assert.That(() =>
826+
{
827+
Profiler.BeginSample(kProfilerRegion);
828+
Set(mouse.position, new Vector2(123, 234));
829+
Set(mouse.position, new Vector2(234, 345));
830+
Press(mouse.leftButton);
831+
Profiler.EndSample();
832+
}, Is.Not.AllocatingGCMemory());
833+
}
834+
792835
// The tracked device tests fail with NullReferenceException in the windows editor on yamato. I cannot reproduce this locally, so will disable them on windows for now.
793836
#if !UNITY_EDITOR_WIN
794837

@@ -824,8 +867,8 @@ protected override void FinishSetup()
824867
}
825868

826869
[UnityTest]
827-
[Category("Actions")]
828-
public IEnumerator Actions_CanDriveUIFromTrackedDevice()
870+
[Category("UI")]
871+
public IEnumerator UI_CanDriveUIFromTrackedDevice()
829872
{
830873
// Create device.
831874
InputSystem.RegisterLayout<TestTrackedDevice>();
@@ -958,8 +1001,8 @@ public IEnumerator Actions_CanDriveUIFromTrackedDevice()
9581001
}
9591002

9601003
[UnityTest]
961-
[Category("Actions")]
962-
public IEnumerator Actions_CanDriveUIFromMultipleTrackedDevices()
1004+
[Category("UI")]
1005+
public IEnumerator UI_CanDriveUIFromMultipleTrackedDevices()
9631006
{
9641007
// Create device.
9651008
InputSystem.RegisterLayout<TestTrackedDevice>();

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ however, it has to be formatted properly to pass verification tests.
1212
### Fixed
1313

1414
- XR controllers and HMDs have proper display names in the UI again. This regressed in preview.4 such that all XR controllers were displayed as just "XR Controller" in the UI and all HMDs were displayed as "XR HMD".
15+
- `InputSystemUIInputModule` no longer generates GC heap garbage every time mouse events are processed.
1516

1617
#### Actions
1718

0 commit comments

Comments
 (0)