Skip to content

Commit 89c29e4

Browse files
Merge branch 'develop' into bugfix/uum-138143-button-press-points-for-stickcontrol-and-vector2-add-functionality
2 parents 6b3acd1 + 80429b2 commit 89c29e4

6 files changed

Lines changed: 114 additions & 4 deletions

File tree

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99

1010
### Fixed
1111

12+
- Fixed `InputRecorder` playback not starting when the Game View is not focused in the Editor [ISXB-1319](https://jira.unity3d.com/browse/ISXB-1319)
1213
- Fixed a `NullReferenceException` thrown when removing all action maps [UUM-137116](https://jira.unity3d.com/browse/UUM-137116)
1314
- Simplified default setting messaging by consolidating repetitive messages into a single HelpBox.
1415
- Fixed a `NullPointerReferenceException` thrown in `InputManagerStateMonitors.FireStateChangeNotifications` logging by adding validation [UUM-136095].

Packages/com.unity.inputsystem/Documentation~/Devices.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ The Editor reloads the C# application domain whenever it reloads and recompiles
167167

168168
Note that layout registrations do not persist across domain reloads. Instead, the Input System relies on all registrations to become available as part of the initialization process (for example, by using `[InitializeOnLoad]` to run registration as part of the domain startup code in the Editor). This allows you to change registrations and layouts in script, and the change to immediately take effect after a domain reload.
169169

170+
##### Support for Configurable Enter Play Mode
171+
172+
Input System 1.20.0 and later supports Configurable Enter Play Mode, which allows entering Play mode with domain reload disabled. For more information, refer to [Configuring how Unity enters Play mode](https://docs.unity3d.com/Manual/configurable-enter-play-mode.html) and [Enter Play mode with domain reload disabled](https://docs.unity3d.com/Manual/domain-reloading.html).
173+
170174
## Native Devices
171175

172176
Devices that the [native backend](xref:input-system-architecture#native-backend) reports are considered native (as opposed to Devices created from script code). To identify these Devices, you can check the [`InputDevice.native`](xref:UnityEngine.InputSystem.InputDevice.native) property.

Packages/com.unity.inputsystem/Documentation~/Events.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ trace.Dispose();
223223

224224
Dispose event traces after use, so that they do not leak memory on the unmanaged (C++) memory heap.
225225

226+
> [!NOTE]
227+
> **Keyboard text input is not replayed to UI text fields.** Keyboard state (key presses) is captured and replayed correctly and remains accessible via `Keyboard.current`. However, there is a known limitation with character delivery to UI Framework components (uGUI `InputField` or UI Toolkit `TextField`). These components receive text through a separate native pipeline that is not fed by event replay. As a result, text typed into UI text fields during recording will not appear during playback.
228+
226229
You can also write event traces out to files/streams, load them back in, and replay recorded streams.
227230

228231
```CSharp

Packages/com.unity.inputsystem/InputSystem/Runtime/Events/InputEventTrace.cs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,9 @@ public class ReplayController : IDisposable
10721072
private double m_StartTimeAsPerRuntime;
10731073
private int m_AllEventsByTimeIndex = 0;
10741074
private List<InputEventPtr> m_AllEventsByTime;
1075+
#if UNITY_EDITOR
1076+
private bool m_EditorEventPassthroughActive;
1077+
#endif
10751078

10761079
internal ReplayController(InputEventTrace trace)
10771080
{
@@ -1088,12 +1091,52 @@ public void Dispose()
10881091
{
10891092
InputSystem.onBeforeUpdate -= OnBeginFrame;
10901093
finished = true;
1091-
1094+
#if UNITY_EDITOR
1095+
StopEditorEventPassthrough();
1096+
#endif
10921097
foreach (var device in m_CreatedDevices)
10931098
InputSystem.RemoveDevice(device);
10941099
m_CreatedDevices = default;
10951100
}
10961101

1102+
#if UNITY_EDITOR
1103+
private void StartEditorEventPassthrough()
1104+
{
1105+
if (!m_EditorEventPassthroughActive)
1106+
{
1107+
m_EditorEventPassthroughActive = true;
1108+
InputManager.StartEditorEventPassthrough();
1109+
}
1110+
}
1111+
1112+
private void StopEditorEventPassthrough()
1113+
{
1114+
// Clean up any pending deferred stop.
1115+
InputSystem.onAfterUpdate -= DeferredStopEditorEventPassthrough;
1116+
1117+
if (m_EditorEventPassthroughActive)
1118+
{
1119+
m_EditorEventPassthroughActive = false;
1120+
InputManager.StopEditorEventPassthrough();
1121+
}
1122+
}
1123+
1124+
// Defers passthrough stop to after the current update so events already queued
1125+
// in the native buffer are still processed with passthrough active.
1126+
private void ScheduleStopEditorEventPassthrough()
1127+
{
1128+
if (!m_EditorEventPassthroughActive)
1129+
return;
1130+
InputSystem.onAfterUpdate += DeferredStopEditorEventPassthrough;
1131+
}
1132+
1133+
private void DeferredStopEditorEventPassthrough()
1134+
{
1135+
InputSystem.onAfterUpdate -= DeferredStopEditorEventPassthrough;
1136+
StopEditorEventPassthrough();
1137+
}
1138+
1139+
#endif
10971140
/// <summary>
10981141
/// Replay events recorded from <paramref name="recordedDevice"/> on device <paramref name="playbackDevice"/>.
10991142
/// </summary>
@@ -1249,6 +1292,9 @@ public ReplayController Rewind()
12491292
public ReplayController PlayAllFramesOneByOne()
12501293
{
12511294
finished = false;
1295+
#if UNITY_EDITOR
1296+
StartEditorEventPassthrough();
1297+
#endif
12521298
InputSystem.onBeforeUpdate += OnBeginFrame;
12531299
return this;
12541300
}
@@ -1267,6 +1313,9 @@ public ReplayController PlayAllFramesOneByOne()
12671313
public ReplayController PlayAllEvents()
12681314
{
12691315
finished = false;
1316+
#if UNITY_EDITOR
1317+
StartEditorEventPassthrough();
1318+
#endif
12701319
try
12711320
{
12721321
while (MoveNext(true, out var eventPtr))
@@ -1311,6 +1360,9 @@ public ReplayController PlayAllEventsAccordingToTimestamps()
13111360

13121361
// Start playback.
13131362
finished = false;
1363+
#if UNITY_EDITOR
1364+
StartEditorEventPassthrough();
1365+
#endif
13141366
m_StartTimeAsPerFirstEvent = -1;
13151367
m_AllEventsByTimeIndex = -1;
13161368
InputSystem.onBeforeUpdate += OnBeginFrame;
@@ -1381,6 +1433,11 @@ private void Finished()
13811433
{
13821434
finished = true;
13831435
InputSystem.onBeforeUpdate -= OnBeginFrame;
1436+
#if UNITY_EDITOR
1437+
// Defer passthrough stop so events already queued in the native buffer
1438+
// this frame are still processed with passthrough active.
1439+
ScheduleStopEditorEventPassthrough();
1440+
#endif
13841441
m_OnFinished?.Invoke();
13851442
}
13861443

Packages/com.unity.inputsystem/InputSystem/Runtime/InputManager.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,45 @@ public bool runPlayerUpdatesInEditMode
492492
set => m_RunPlayerUpdatesInEditMode = value;
493493
}
494494

495+
/// <summary>
496+
/// Ref-counted flag that bypasses Game View focus gating for event processing.
497+
/// When greater than zero, events are processed as if the Game View has focus,
498+
/// regardless of actual focus state. This affects event routing, disabled-device
499+
/// discard, and UI module processing.
500+
/// </summary>
501+
/// <remarks>
502+
/// Use <see cref="StartEditorEventPassthrough"/> / <see cref="StopEditorEventPassthrough"/>
503+
/// to manage this counter. Follows the same pattern as
504+
/// <c>AssetDatabase.StartAssetEditing/StopAssetEditing</c>.
505+
/// </remarks>
506+
/// <seealso cref="StartEditorEventPassthrough"/>
507+
/// <seealso cref="StopEditorEventPassthrough"/>
508+
private int m_EditorEventPassthroughCount;
509+
510+
internal bool isEditorEventPassthroughActive => m_EditorEventPassthroughCount > 0;
511+
512+
/// <summary>
513+
/// Signals that events should bypass Game View focus gating. Ref-counted:
514+
/// each call must be balanced by a corresponding <see cref="StopEditorEventPassthrough"/>.
515+
/// </summary>
516+
internal static void StartEditorEventPassthrough()
517+
{
518+
++InputSystem.s_Manager.m_EditorEventPassthroughCount;
519+
}
520+
521+
/// <summary>
522+
/// Signals that the caller no longer needs events to bypass Game View focus gating.
523+
/// Decrements the ref count started by <see cref="StartEditorEventPassthrough"/>.
524+
/// </summary>
525+
internal static void StopEditorEventPassthrough()
526+
{
527+
if (InputSystem.s_Manager != null && InputSystem.s_Manager.m_EditorEventPassthroughCount > 0)
528+
--InputSystem.s_Manager.m_EditorEventPassthroughCount;
529+
}
530+
495531
#endif // UNITY_EDITOR
496532

533+
497534
private bool gameIsPlaying =>
498535
#if UNITY_EDITOR
499536
(m_Runtime.isInPlayMode && !m_Runtime.isEditorPaused) || m_RunPlayerUpdatesInEditMode;
@@ -504,7 +541,7 @@ public bool runPlayerUpdatesInEditMode
504541

505542
private bool gameHasFocus =>
506543
#if UNITY_EDITOR
507-
m_RunPlayerUpdatesInEditMode || applicationHasFocus || gameShouldGetInputRegardlessOfFocus;
544+
m_RunPlayerUpdatesInEditMode || applicationHasFocus || gameShouldGetInputRegardlessOfFocus || isEditorEventPassthroughActive;
508545
#else
509546
applicationHasFocus || gameShouldGetInputRegardlessOfFocus;
510547
#endif
@@ -3372,7 +3409,12 @@ private unsafe void ProcessEventBuffer(InputUpdateType updateType, ref InputEven
33723409

33733410
// If device is disabled, we let the event through only in certain cases.
33743411
// Removal and configuration change events should always be processed.
3412+
// During replay, allow events through for devices disabled due to background
3413+
// focus loss — the replay intentionally re-injects events for those devices.
33753414
if (device != null && !device.enabled &&
3415+
#if UNITY_EDITOR
3416+
!isEditorEventPassthroughActive &&
3417+
#endif
33763418
currentEventType != DeviceRemoveEvent.Type &&
33773419
currentEventType != DeviceConfigurationEvent.Type &&
33783420
(device.m_DeviceFlags & (InputDevice.DeviceFlags.DisabledInRuntime |
@@ -3411,7 +3453,6 @@ private unsafe void ProcessEventBuffer(InputUpdateType updateType, ref InputEven
34113453
#endif
34123454
if (!shouldProcess)
34133455
{
3414-
// Skip event if PreProcessEvent considers it to be irrelevant.
34153456
m_InputEventStream.Advance(false);
34163457
continue;
34173458
}

Packages/com.unity.inputsystem/InputSystem/Runtime/Plugins/UI/InputSystemUIInputModule.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,11 @@ private bool shouldIgnoreFocus
997997
// if running in the background is enabled, we already have rules in place what kind of input
998998
// is allowed through and what isn't. And for the input that *IS* allowed through, the UI should
999999
// react.
1000-
get => explictlyIgnoreFocus || InputRuntime.s_Instance.runInBackground;
1000+
get => explictlyIgnoreFocus || InputRuntime.s_Instance.runInBackground
1001+
#if UNITY_EDITOR
1002+
|| InputSystem.s_Manager.isEditorEventPassthroughActive
1003+
#endif
1004+
;
10011005
}
10021006

10031007
/// <summary>

0 commit comments

Comments
 (0)