Skip to content

Commit 3aa395f

Browse files
author
Rene Damm
authored
FIX: Missing InputActionReferences when renaming actions (case 1129145, #1117).
1 parent 675f70f commit 3aa395f

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ however, it has to be formatted properly to pass verification tests.
3232
- The importer for `.inputactions` assets will now check out from version control the generated .cs file when overwriting it – which only happens if the contents differ ([case 1222972](https://issuetracker.unity3d.com/issues/inputsystem-editor-generated-c-number-file-is-not-checked-out-when-overwriting)).
3333
- The editor for `.inputactions` assets will now check out from version control the asset before saving it.
3434
- Drag-reordering action maps no longer throws "Should have drop target" asserts in the console (case [1229146](https://issuetracker.unity3d.com/issues/inputsystem-reordering-of-actionmaps-in-input-action-window-fails-and-throws-should-have-drop-target-error)).
35+
- References to `InputActionReference` objects created by the importer for `.inputactions` files are no longer broken when the action referenced by the object is renamed ([case 1229145](https://issuetracker.unity3d.com/issues/inputsystem-inputactionreference-loses-guid-when-its-action-is-moved-or-renamed-in-the-inputaction-asset)).
36+
* __NOTE: This fix does not apply to existing `InputActionReference` instances.__ The problem was inherent in the internal file IDs generated for actions &ndash; which were affected by action and map names. Thus, changing the name of an action or map would change the resulting file ID of the `InputActionReference`.<br>However, changing file IDs will break any existing reference to the object. Thus we had to preserve the existing `InputActionReference` objects under their original file ID. We hide them in the Project Browser, however. The ones that are visible now have the new, fixed file IDs.<br>To switch existing `InputActionReference` properties to the new file IDs, simply replace them with the newly created `InputActionReference`.
3537

3638
### Changed
3739

Packages/com.unity.inputsystem/InputSystem/Actions/InputActionReference.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
using System;
22
using System.Linq;
33

4+
////REVIEW: Can we somehow make this a simple struct? The one problem we have is that we can't put struct instances as sub-assets into
5+
//// the import (i.e. InputActionImporter can't do AddObjectToAsset with them). However, maybe there's a way around that. The thing
6+
//// is that we really want to store the asset reference plus the action GUID on the *user* side, i.e. the referencing side. Right
7+
//// now, what happens is that InputActionImporter puts these objects along with the reference and GUID they contain in the
8+
//// *imported* object, i.e. right with the asset. This partially defeats the whole purpose of having these objects and it means
9+
//// that now the GUID doesn't really matter anymore. Rather, it's the file ID that now has to be stable.
10+
////
11+
//// If we always store the GUID and asset reference on the user side, we can put the serialized data *anywhere* and it'll remain
12+
//// save and proper no matter what we do in InputActionImporter.
13+
414
////REVIEW: should this throw if you try to assign an action that is not a singleton?
515

616
////REVIEW: akin to this, also have an InputActionMapReference?

Packages/com.unity.inputsystem/InputSystem/Editor/AssetEditor/InputActionAssetManager.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.IO;
44
using UnityEditor;
55

6+
////TODO: ensure that GUIDs in the asset are unique
7+
68
namespace UnityEngine.InputSystem.Editor
79
{
810
/// <summary>

Packages/com.unity.inputsystem/InputSystem/Editor/AssetImporter/InputActionImporter.cs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#if UNITY_EDITOR
22
using System;
33
using System.IO;
4+
using System.Linq;
45
using UnityEditor;
56
using UnityEditor.Experimental.AssetImporters;
67
using UnityEngine.InputSystem.Utilities;
@@ -22,7 +23,7 @@ namespace UnityEngine.InputSystem.Editor
2223
[ScriptedImporter(kVersion, InputActionAsset.Extension)]
2324
internal class InputActionImporter : ScriptedImporter
2425
{
25-
private const int kVersion = 10;
26+
private const int kVersion = 11;
2627

2728
private const string kActionIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputAction.png";
2829
private const string kAssetIcon = "Packages/com.unity.inputsystem/InputSystem/Editor/Icons/InputActionAsset.png";
@@ -90,25 +91,27 @@ public override void OnImportAsset(AssetImportContext ctx)
9091
ctx.AddObjectToAsset("<root>", asset, assetIcon);
9192
ctx.SetMainObject(asset);
9293

93-
// Make sure all the elements in the asset have GUIDs.
94+
// Make sure all the elements in the asset have GUIDs and that they are indeed unique.
9495
var maps = asset.actionMaps;
9596
foreach (var map in maps)
9697
{
9798
// Make sure action map has GUID.
98-
if (string.IsNullOrEmpty(map.m_Id))
99+
if (string.IsNullOrEmpty(map.m_Id) || asset.actionMaps.Count(x => x.m_Id == map.m_Id) > 1)
99100
map.GenerateId();
100101

101102
// Make sure all actions have GUIDs.
102103
foreach (var action in map.actions)
103104
{
104-
if (string.IsNullOrEmpty(action.m_Id))
105+
var actionId = action.m_Id;
106+
if (string.IsNullOrEmpty(actionId) || asset.actionMaps.Sum(m => m.actions.Count(a => a.m_Id == actionId)) > 1)
105107
action.GenerateId();
106108
}
107109

108110
// Make sure all bindings have GUIDs.
109111
for (var i = 0; i < map.m_Bindings.LengthSafe(); ++i)
110112
{
111-
if (string.IsNullOrEmpty(map.m_Bindings[i].m_Id))
113+
var bindingId = map.m_Bindings[i].m_Id;
114+
if (string.IsNullOrEmpty(bindingId) || asset.actionMaps.Sum(m => m.bindings.Count(b => b.m_Id == bindingId)) > 1)
112115
map.m_Bindings[i].GenerateId();
113116
}
114117
}
@@ -128,7 +131,23 @@ public override void OnImportAsset(AssetImportContext ctx)
128131
objectName = $"{map.name}/{action.name}";
129132

130133
actionReference.name = objectName;
131-
ctx.AddObjectToAsset(objectName, actionReference, actionIcon);
134+
ctx.AddObjectToAsset(action.m_Id, actionReference, actionIcon);
135+
136+
// Backwards-compatibility (added for 1.0.0-preview.7).
137+
// We used to call AddObjectToAsset using objectName instead of action.m_Id as the object name. This fed
138+
// the action name (*and* map name) into the hash generation that was used as the basis for the file ID
139+
// object the InputActionReference object. Thus, if the map and/or action name changed, the file ID would
140+
// change and existing references to the InputActionReference object would become invalid.
141+
//
142+
// What we do here is add another *hidden* InputActionReference object with the same content to the
143+
// asset. This one will use the old file ID and thus preserve backwards-compatibility. We should be able
144+
// to remove this for 2.0.
145+
//
146+
// Case: https://fogbugz.unity3d.com/f/cases/1229145/
147+
var backcompatActionReference = Instantiate(actionReference);
148+
backcompatActionReference.name = objectName; // Get rid of the (Clone) suffix.
149+
backcompatActionReference.hideFlags = HideFlags.HideInHierarchy;
150+
ctx.AddObjectToAsset(objectName, backcompatActionReference, actionIcon);
132151
}
133152
}
134153

0 commit comments

Comments
 (0)