Skip to content

Commit 0034736

Browse files
authored
FIX: Fixed ArgumentNullException: Value cannot be null. during the migration of Project-wide Input Actions (ISXB-1105) (#2037)
* Revert "CHANGE: Performance improvement - removed project-wide asset migration code (#2025)" * Fixed ArgumentNullException during the migration of Project-wide Input Actions
1 parent 3d5266a commit 0034736

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ however, it has to be formatted properly to pass verification tests.
1212

1313
### Fixed
1414
- Fixed an issue causing the Action context menu to not show on right click when right clicking an action in the Input Action Editor [ISXB-1134](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1134).
15+
- Fixed `ArgumentNullException: Value cannot be null.` during the migration of Project-wide Input Actions from `InputManager.asset` to `InputSystem_Actions.inputactions` asset which lead do the lost of the configuration [ISXB-1105](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1105)
16+
17+
### Changed
18+
- Added back the InputManager to InputSystem project-wide asset migration code with performance improvement (ISX-2086)
1519

1620
## [1.11.2] - 2024-10-16
1721

Packages/com.unity.inputsystem/InputSystem/Editor/ProjectWideActions/ProjectWideActionsAsset.cs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,25 @@ internal static class ProjectWideActionsAsset
1717

1818
internal static class ProjectSettingsProjectWideActionsAssetConverter
1919
{
20+
private const string kAssetPathInputManager = "ProjectSettings/InputManager.asset";
21+
private const string kAssetNameProjectWideInputActions = "ProjectWideInputActions";
22+
2023
class ProjectSettingsPostprocessor : AssetPostprocessor
2124
{
25+
private static bool migratedInputActionAssets = false;
26+
2227
#if UNITY_2021_2_OR_NEWER
2328
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload)
2429
#else
2530
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
2631
#endif
2732
{
33+
if (!migratedInputActionAssets && importedAssets.Contains(kAssetPathInputManager))
34+
{
35+
MoveInputManagerAssetActionsToProjectWideInputActionAsset();
36+
migratedInputActionAssets = true;
37+
}
38+
2839
if (!Application.isPlaying)
2940
{
3041
// If the Library folder is deleted, InputSystem will fail to retrieve the assigned Project-wide Asset because this look-up occurs
@@ -35,6 +46,103 @@ private static void OnPostprocessAllAssets(string[] importedAssets, string[] del
3546
}
3647
}
3748
}
49+
50+
private static void MoveInputManagerAssetActionsToProjectWideInputActionAsset(bool allowRetry = true)
51+
{
52+
var objects = AssetDatabase.LoadAllAssetsAtPath(EditorHelpers.GetPhysicalPath(kAssetPathInputManager));
53+
if (objects == null)
54+
return;
55+
56+
var inputActionsAssets = objects.Where(o => o != null && o.name == kAssetNameProjectWideInputActions && o is InputActionAsset);
57+
58+
if (!inputActionsAssets.Any()) return;
59+
60+
Debug.Log("Migrating Project-wide Input Actions from InputManager.asset to InputSystem_Actions.inputactions asset");
61+
62+
// workarround for serialization bug with ScriptableObject in ProjectSettings during reimporting all asset, it should not be null
63+
if (allowRetry)
64+
{
65+
foreach (InputActionAsset inputActionsAsset in inputActionsAssets)
66+
{
67+
if (inputActionsAsset.m_ActionMaps == null)
68+
{
69+
// unload asset to avoid serialization bug and will try again later
70+
Resources.UnloadAsset(inputActionsAsset);
71+
Debug.Log($"Unexpected null action map encounted during the migration, will try again once later");
72+
EditorApplication.delayCall += () => { MoveInputManagerAssetActionsToProjectWideInputActionAsset(allowRetry: false); };
73+
return;
74+
}
75+
}
76+
}
77+
78+
foreach (InputActionAsset inputActionsAsset in inputActionsAssets)
79+
{
80+
if (inputActionsAsset != default)
81+
{
82+
// sanity check to avoid saving a badly serialized asset or empty asset
83+
if (inputActionsAsset.m_ActionMaps.LengthSafe() == 0)
84+
{
85+
continue;
86+
}
87+
string path = ProjectWideActionsAsset.kDefaultAssetPath;
88+
89+
if (File.Exists(EditorHelpers.GetPhysicalPath(path)))
90+
{
91+
// We already have a path containing inputactions, find a new unique filename
92+
//
93+
// eg Assets/InputSystem_Actions.inputactions ->
94+
// Assets/InputSystem_Actions (1).inputactions ->
95+
// Assets/InputSystem_Actions (2).inputactions ...
96+
//
97+
string[] files = Directory.GetFiles("Assets", "*.inputactions");
98+
List<string> names = new List<string>();
99+
for (int i = 0; i < files.Length; i++)
100+
{
101+
names.Add(System.IO.Path.GetFileNameWithoutExtension(files[i]));
102+
}
103+
string unique = ObjectNames.GetUniqueName(names.ToArray(), kDefaultAssetName);
104+
path = "Assets/" + unique + ".inputactions";
105+
}
106+
107+
var json = inputActionsAsset.ToJson();
108+
InputActionAssetManager.SaveAsset(EditorHelpers.GetPhysicalPath(path), json);
109+
110+
Debug.Log($"Migrated Project-wide Input Actions from '{kAssetPathInputManager}' to '{path}' asset");
111+
112+
// Update current project-wide settings if needed (don't replace if already set to something else)
113+
//
114+
if (InputSystem.actions == null || InputSystem.actions.name == kAssetNameProjectWideInputActions)
115+
{
116+
InputSystem.actions = (InputActionAsset)AssetDatabase.LoadAssetAtPath(path, typeof(InputActionAsset));
117+
Debug.Log($"Loaded Project-wide Input Actions from '{path}' asset");
118+
}
119+
}
120+
}
121+
122+
123+
bool hasChanged = false;
124+
// Handle deleting all InputActionAssets as older 1.8.0 pre release could create more than one project wide input asset in the file
125+
foreach (var obj in objects)
126+
{
127+
if (obj is InputActionReference)
128+
{
129+
var actionReference = obj as InputActionReference;
130+
AssetDatabase.RemoveObjectFromAsset(obj);
131+
Object.DestroyImmediate(actionReference);
132+
hasChanged = true;
133+
}
134+
else if (obj is InputActionAsset)
135+
{
136+
AssetDatabase.RemoveObjectFromAsset(obj);
137+
hasChanged = true;
138+
}
139+
}
140+
141+
if (hasChanged == true)
142+
{
143+
AssetDatabase.SaveAssets();
144+
}
145+
}
38146
}
39147

40148
// Returns the default asset path for where to create project-wide actions asset.

0 commit comments

Comments
 (0)