Skip to content

ISXB-512, ISXB-521 Fix TrackedPoseDriver serialization migration#1705

Merged
jamesmcgill merged 9 commits intodevelopfrom
ISXB-512-fix-tpd-serialization-migration
Jul 20, 2023
Merged

ISXB-512, ISXB-521 Fix TrackedPoseDriver serialization migration#1705
jamesmcgill merged 9 commits intodevelopfrom
ISXB-512-fix-tpd-serialization-migration

Conversation

@chris-massie
Copy link
Copy Markdown
Collaborator

Description

Fixes an issue where the bindings were cleared due to invalid serialization migration logic in some cases.

  • ISXB-512 TrackedPoseDriver bindings disappear when modifying an XR Origin Prefab
  • ISXB-521 Tracked Pose Driver (Input System) bindings on a prefab become lost upon exiting editing the Prefab

Changes made

Modified the serialization logic so it won't replace the newer InputActionProperties if either the reference or embedded input action are already set.

I also made some other fixes I discovered while fixing the above:
Currently, the IDs of Input Actions are generated automatically when calling the id property or when the InputAction property drawer draws the field. However, if you create a GameObject and add a component with one serialized through API, the m_Id field wouldn't be generated in the serialized asset. This was causing the GameObject > XR > XR Origin (VR) rig created to not have those fields set since it was on a child GameObject. If a user dragged the root to create a prefab, when they would click on the child GameObject in the prefab or in the Hierarchy window, it would create a prefab override with new generated IDs. This change makes the constructor generate an ID so that it doesn't need to be visible in the Inspector window to be generated.

Also fixed the Clone methods to have it copy the m_Flags field so that the Initial State Check checkbox is copied.

Notes

This fix still does not fix the issue of nested prefabs where the parent prefab has an override to add a new input binding. The base prefab will already have the InputActionProperty upgraded, so the modified old deprecated field with the additional singleton bindings doesn't get copied over to the new property. There doesn't seem to be a way to reliably detect this situation. However, this is already the case with the old migration method, so it doesn't make it worse.

It's still possible for a prefab instance to have a noisy prefab override of the action name since the name, like the ID, is generated by the property drawer. However, if you create the InputAction with a non-empty name argument, it won't have that 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.
    • FogBugz ticket attached, example ([case %number%](https://issuetracker.unity3d.com/issues/...)).
    • FogBugz is marked as "Resolved" with next release version correctly set.
  • 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.

- Removed the no longer necessary m_HasMigratedActions field since it only copies over from the old deprecated fields if the new property has not been initialized.
- This fix still does not fix the issue of nested prefabs where the parent prefab has an override to add a new input binding. The base prefab will already have the InputActionProperty upgraded, so the modified old deprecated field with the additional singleton bindings doesn't get copied over to the new property. There doesn't seem to be a way to reliably detect this situation.
…generated for actions in constructor

- When adding a serialized InputAction (or with an InputActionProperty), the ID Guid may not be generated, which could cause noise in prefab overrides. Having the constructor generate an ID initially instead of relying on the id property or property drawer generate one and write to the asset makes it more consistent. This specifically fixes the GameObject > XR > XR Origin (VR) creation shortcut not having IDs set since the Inspector is never visible before making a prefab.
Comment on lines +15 to +21
### Changed
- Changed the `InputAction` constructors so it generates an ID for the action and the optional binding parameter. This is intended to improve the serialization of input actions on behaviors when created through API when the property drawer in the Inspector window does not have a chance to generate an ID.

### Fixed
- Fixed serialization migration in the Tracked Pose Driver component causing bindings to clear when prefabs are used in some cases ([case ISXB-512](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-512), [case ISXB-521](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-521)).
- Fixed the `Clone` methods of `InputAction` and `InputActionMap` so it copies the Initial State Check flag (`InputAction.wantsInitialStateCheck`) of input actions.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we missed the window on 1.6.2, but I'll talk to Lyndon about fast-tracking another patch release to fix this.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was a bad merge, I fixed it by moving it from 1.6.2 to Unreleased.

@vrdave-unity vrdave-unity added the bug Issues where existsing functionality misbehaves label Jul 13, 2023
Copy link
Copy Markdown
Collaborator

@jamesmcgill jamesmcgill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.
You might need to pull in latest develop to fix up the Dry Run failures there (likely requires another CHANGELOG)

[SerializeField] private bool m_UseReference;
[SerializeField] private InputAction m_Action;
[SerializeField] private InputActionReference m_Reference;
[SerializeField] internal bool m_UseReference;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would testing InputActionProperty.action for null rather than exposing these fields have the same result in TrackedPoseDriver?

It's implementation is:
public InputAction action => m_UseReference ? m_Reference != null ? m_Reference.action : null : m_Action;
which I think will return null in all cases m_Reference and m_Action will both be null.

Otherwise perhaps adding a new member here rather than exposing the private fields so that the TrackedPoseDriver code is not so dependent on how this is implemented.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't be exactly the same. If a user clicked Use Reference to toggle the value in the Inspector window, the action property might start evaluating to null but one of its fields is already set. I wanted the migration code in TPD to skip copying the value from the old serialized field if any InputActionProperty value had already been created.

Instead of making the fields internal, I could expose all the serialized fields in new public properties, which goes along with the Unity coding style rules that all Inspector window values are accessible through API, but that would be an API addition and thus this PR couldn't be included in a patch release.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, I get the logic now.
There is another PR incoming that looks like it will need a minor bump, so now might be a good opportunity for getting something in (#1701).

m_Reference and m_Action have public properties already though and adding alternative versions of those that don't hold the invariants might be confusing. I don't know if exposing just m_UseReference will be enough for you to work with?

Alternatively perhaps another method like IsEmpty or IsNull to make the code in TrackedPoseDriver simple.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if I added a property for m_UseReference, I wouldn't be able to duplicate the logic exactly.

To try to address this feedback, I added new internal getter properties for the m_Action and m_Reference fields and reverted the fields back to private, and updated TPD to use those instead.

In the future, we can make them public and potentially add setters along with a property for m_UseReference, but we were scheduling to include this bug fix in a patch release so we can't add public properties yet.

# Conflicts:
#	Packages/com.unity.inputsystem/CHANGELOG.md
…ernal

- We can potentially make the new properties public and even add setters along with a property for useReference, but this way of keeping them internal will avoid having to bump minor version to fix this bug.
# Conflicts:
#	Packages/com.unity.inputsystem/CHANGELOG.md
@jamesmcgill jamesmcgill merged commit ff181b1 into develop Jul 20, 2023
@jamesmcgill jamesmcgill deleted the ISXB-512-fix-tpd-serialization-migration branch July 20, 2023 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Issues where existsing functionality misbehaves

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants