Skip to content

Conversation

@Extrys
Copy link

@Extrys Extrys commented Nov 26, 2025

Description

Enhance InputEventTrace so device usages (e.g. LeftHand, RightHand) are captured, serialized, and restored when recording and replaying input. This prevents XR devices recreated from traces from losing their usages and failing to match XR control schemes or being overridden by live input.

Key changes:

  • Device usages are serialized to JSON and stored in DeviceInfo when tracing input events, allowing accurate recreation of usages during replay.
  • The WriteTo and ReadFrom methods now handle the new m_UsagesJson field so usages are included in the trace file and restored on load.
  • During device mapping in replay, usages from the original device are restored on the recreated device, and a UsageChanged notification is triggered to ensure XR devices correctly participate in action resolution and control schemes.
  • Added UsagesJsonWrapper to serialize/deserialize device usages as JSON, with helpers to convert between arrays and ReadOnlyArray<InternedString>.
  • File format version updated so that older traces can still be deserialized correctly (they simply have no usages stored).

Testing status & QA

  • Manually tested in the editor with:
    • Meta Quest 3 controllers (OpenXR) using recorded traces.
    • Mouse and keyboard input traces.
  • Verified that:
    • XR devices now replay correctly with their Left/Right usages restored.
    • Saving and loading traces preserves XR device usages.
    • All the XR recording still working even if Initialize XR on Startup is disabled.
    • Older files still loading properly (without usages, as before).

No new automated tests have been added.

Overall Product Risks

Complexity: low
Halo Effect: Low

Potential risk areas:

  • Replay on new devices path go through this code changes, not only XR usage, although the change should be backwards compatible for non-XR devices.

Comments to reviewers

Main things to focus on:

  • Verify XR input replay with controllers (Left/Right) and confirm usages are restored correctly and actions/control schemes behave as expected.
  • Confirm that traces recorded prior to this change still load and replay without regressions (apart from not having usages stored).

Note

On some headsets (e.g. Meta Quest), the XRHMD tracking state may remain active even when the device appears idle. In those cases, replayed rotation can still compete with live HMD rotation unless rotation input is configured accordingly (e.g. PassThrough mode Input Action or headset powered off). This appears to be platform/Input system behaviour rather than an InputEventTrace issue.

Checklist

Before review:

  • Changelog entry added.
    • Explains the change in Changed, Fixed, Added sections.
    • For API change contains an example snippet and/or migration example.
    • JIRA ticket linked, example (case %%). If it is a private issue, just add the case ID without a link.
    • Jira port for the next release set as "Resolved".
  • Tests added/changed, if applicable.
    • Functional tests Area_CanDoX, Area_CanDoX_EvenIfYIsTheCase, Area_WhenIDoX_AndYHappens_ThisIsTheResult.
    • Performance tests.
    • Integration tests.
  • Docs for new/changed API's.
    • Xmldoc cross references are set correctly.
    • Added explanation how the API works.
    • Usage code examples added.
    • The manual is updated, if needed.

During merge:

  • Commit message for squash-merge is prefixed with one of the list:
    • NEW: ___.
    • FIX: ___.
    • DOCS: ___.
    • CHANGE: ___.
    • RELEASE: 1.1.0-preview.3.

Enhance InputEventTrace to store and retrieve device usages
facilitating accurate device recreation during input replay.

This fixes XR devices not replaying due not writing its Left/Right usages

Also included original device resetting to avoid incorrect rest state passthrough input to override replay input
FIX: XR input replay preserves device usages
@unity-cla-assistant
Copy link

unity-cla-assistant commented Nov 26, 2025

CLA assistant check
All committers have signed the CLA.

@u-pr-agent
Copy link
Contributor

u-pr-agent bot commented Nov 26, 2025

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪

The PR involves changes to file serialization formats and core input replay logic, requiring careful verification of backward compatibility and side effects, but the code volume is small.
🏅 Score: 88

The changes are well-structured, backward compatible, and address the specific issue with XR device usages; however, there is a potential risk involving device ID collisions during replay that should be addressed.
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Possible Device ID Collision

In ApplyDeviceMapping, the code uses deviceInfo.m_DeviceId (from the trace) to look up and reset a device in the current session via InputSystem.GetDeviceById. If the trace was recorded in a different session (e.g., loaded from a file), the trace device ID is arbitrary relative to the current session's devices. This could inadvertently reset an unrelated device that happens to share the same integer ID. Consider validating that the device found actually matches the trace device (e.g., by layout) or ensuring this logic only runs when appropriate.

var originalDevice = InputSystem.GetDeviceById(deviceInfo.m_DeviceId);
if (originalDevice != null)
    InputSystem.ResetDevice(originalDevice);
  • Update review

🤖 Helpful? Please react with 👍/👎 | Questions❓Please reach out in Slack #ask-u-pr-agent

@u-pr-agent
Copy link
Contributor

u-pr-agent bot commented Nov 26, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix invalid null assignment to struct

ReadOnlyArray is a struct in the Input System and cannot be assigned null.
Initialize it with default to avoid compilation errors and ensure correct behavior.

Packages/com.unity.inputsystem/InputSystem/Events/InputEventTrace.cs [1517]

-ReadOnlyArray<InternedString> originalUsages = null;
+ReadOnlyArray<InternedString> originalUsages = default;
Suggestion importance[1-10]: 10

__

Why: ReadOnlyArray<T> is a struct in the Unity Input System, so assigning null to it causes a compilation error. Initializing it with default is the correct way to represent an empty array and fixes the build issue.

High
Prevent NullReferenceException on empty JSON

JsonUtility leaves array fields as null if the JSON input is empty or missing the
field. Add a null check for m_usages to prevent a NullReferenceException during
deserialization.

Packages/com.unity.inputsystem/InputSystem/Events/InputEventTrace.cs [1630-1638]

 internal readonly ReadOnlyArray<InternedString> GetUsagesInternedStringArray()
 {
+    if (m_usages == null)
+        return default;
+
     InternedString[] internedUsages = new InternedString[m_usages.Length];
     for (int i = 0; i < m_usages.Length; i++)
     {
         internedUsages[i] = new InternedString(m_usages[i]);
     }
     return new ReadOnlyArray<InternedString>(internedUsages);
 }
Suggestion importance[1-10]: 7

__

Why: JsonUtility sets array fields to null if the corresponding JSON field is missing. Adding a null check for m_usages prevents a NullReferenceException when accessing m_usages.Length during deserialization of incomplete or malformed JSON.

Medium
  • More suggestions

🤖 Helpful? Please react with 👍/👎 | Questions❓Please reach out in Slack #ask-u-pr-agent

@Extrys
Copy link
Author

Extrys commented Nov 27, 2025

Updated branch with the u-pr-agent sugestions, which spotted the device collision issue, so resseting should not be made on that code path

still tough this note being important to have in mind

Note

On some headsets (e.g. Meta Quest), the XRHMD tracking state may remain active even when the device appears idle. In those cases, replayed rotation can still compete with live HMD rotation unless rotation input is configured accordingly (e.g. PassThrough mode Input Action or headset powered off). This appears to be platform/Input system behaviour rather than an InputEventTrace issue.

Its only happening with the Rotation Input action from XR Tracked pose driver
the current cleaner workarround which is pretty straightforward is just making that input action "Passthrough".
That will make the new created XRHMD to "override" the real HMD rotation
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants