Skip to content

Commit 7e50a2a

Browse files
committed
Refactor multiple function objects into a single one in InputActionReference.cs
1 parent 7653046 commit 7e50a2a

2 files changed

Lines changed: 38 additions & 71 deletions

File tree

Packages/com.unity.inputsystem/InputSystem/Editor/InputSystemEditorInitializer.cs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,33 @@ private static void RegisterAssetDatabaseHooks()
276276
InputActionAsset.s_OnMarkAsDirty = DirtyAssetTracker.TrackDirtyInputActionAsset;
277277
InputManager.s_GetProjectWideActions = () => ProjectWideActionsBuildProvider.actionsToIncludeInPlayerBuild;
278278

279-
InputActionReference.s_IsSubAsset = AssetDatabase.IsSubAsset;
280-
InputActionReference.s_GetAssetPath = AssetDatabase.GetAssetPath;
281-
InputActionReference.s_LoadMainAssetAtPath = AssetDatabase.LoadMainAssetAtPath;
279+
InputActionReference.s_CheckImmutableReference = CheckImmutableInputActionReference;
280+
}
281+
282+
/// <summary>
283+
/// Prevents accidental mutation of the source asset if this <see cref="InputActionReference"/> is a
284+
/// persisted sub-asset within a .inputactions <see cref="InputActionAsset"/>.
285+
/// </summary>
286+
private static void CheckImmutableInputActionReference(InputActionReference reference)
287+
{
288+
if (!AssetDatabase.IsSubAsset(reference))
289+
return;
290+
291+
var path = AssetDatabase.GetAssetPath(reference);
292+
if (path == null)
293+
return;
294+
295+
var mainAsset = AssetDatabase.LoadMainAssetAtPath(path);
296+
if (!mainAsset || mainAsset is not InputActionAsset)
297+
return;
298+
299+
throw new InvalidOperationException(
300+
"Attempting to modify an immutable InputActionReference instance " +
301+
"that is part of an .inputactions asset. This is not allowed since it would modify the source " +
302+
"asset in which the reference is serialized and potentially corrupt it. " +
303+
"Instead use InputActionReference.Create(action) to create a new mutable " +
304+
"in-memory instance or serialize it as a separate asset if the intent is for changes to " +
305+
"survive domain reloads.");
282306
}
283307

284308
#if UNITY_INPUT_SYSTEM_ENABLE_UI || PACKAGE_DOCS_GENERATION

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

Lines changed: 11 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ public void Set(InputActionAsset asset, string mapName, string actionName)
137137

138138
private void SetInternal(InputActionAsset assetArg, InputAction actionArg)
139139
{
140-
CheckImmutableReference();
140+
#if UNITY_EDITOR
141+
s_CheckImmutableReference?.Invoke(this);
142+
#endif
141143

142144
// If we are setting the reference in edit-mode, we want the state to be reflected in the serialized
143145
// object and hence assign serialized fields. This is a destructive operation.
@@ -207,13 +209,6 @@ public static InputActionReference Create(InputAction action)
207209
/// This method is used to clear the Action references when exiting PlayMode since those objects are no
208210
/// longer valid.
209211
/// </remarks>
210-
#if UNITY_EDITOR
211-
// Callbacks set by Editor to check asset status without direct UnityEditor dependency
212-
internal static Func<Object, bool> s_IsSubAsset;
213-
internal static Func<Object, string> s_GetAssetPath;
214-
internal static Func<string, Object> s_LoadMainAssetAtPath;
215-
#endif
216-
217212
internal static void InvalidateAll()
218213
{
219214
// It might be possible that Object.FindObjectOfTypeAll(true) would be sufficient here since we only
@@ -224,6 +219,14 @@ internal static void InvalidateAll()
224219
((InputActionReference)obj).Invalidate();
225220
}
226221

222+
#if UNITY_EDITOR
223+
/// <summary>
224+
/// Set by the editor to prevent mutating <see cref="InputActionReference"/> sub-assets inside
225+
/// <see cref="InputActionAsset"/> files. Not used in player builds.
226+
/// </summary>
227+
internal static Action<InputActionReference> s_CheckImmutableReference;
228+
#endif
229+
227230
/// <summary>
228231
/// Clears the cached <see cref="m_Action"/> field for this <see cref="InputActionReference"/> instance.
229232
/// </summary>
@@ -256,65 +259,5 @@ public InputAction ToInputAction()
256259
{
257260
return action;
258261
}
259-
260-
/// <summary>
261-
/// Checks if this input action reference instance can be safely mutated without side effects.
262-
/// </summary>
263-
/// <remarks>
264-
/// This check isn't needed in player builds since ScriptableObject would never be persisted if mutated
265-
/// in a player.
266-
/// </remarks>
267-
/// <exception cref="InvalidOperationException">Thrown if this input action reference is part of an
268-
/// input actions asset and mutating it would have side-effects on the projects assets.</exception>
269-
private void CheckImmutableReference()
270-
{
271-
#if UNITY_EDITOR
272-
// Prevent accidental mutation of the source asset if this InputActionReference is a persisted object
273-
// residing as a sub-asset within a .inputactions asset.
274-
// This is not needed for players since scriptable objects aren't serialized back from within a player.
275-
if (!CanSetReference())
276-
{
277-
throw new InvalidOperationException("Attempting to modify an immutable InputActionReference instance " +
278-
"that is part of an .inputactions asset. This is not allowed since it would modify the source " +
279-
"asset in which the reference is serialized and potentially corrupt it. " +
280-
"Instead use InputActionReference.Create(action) to create a new mutable " +
281-
"in-memory instance or serialize it as a separate asset if the intent is for changes to " +
282-
"survive domain reloads.");
283-
}
284-
#endif // UNITY_EDITOR
285-
}
286-
287-
#if UNITY_EDITOR
288-
// Note that we do a lot of checking here, but it is only for a rather slim (unintended) use case in
289-
// editor and not in final builds. The alternative would be to set a non-serialized field on the reference
290-
// when importing assets which would simplify this class, but it adds complexity to import stage and
291-
// is more difficult to assess from a asset version portability perspective.
292-
private bool CanSetReference()
293-
{
294-
// If callbacks aren't set, allow the operation
295-
if (s_IsSubAsset == null || s_GetAssetPath == null || s_LoadMainAssetAtPath == null)
296-
return true;
297-
298-
// "Immutable" input action references are always sub-assets of InputActionAsset.
299-
var isSubAsset = s_IsSubAsset(this);
300-
if (!isSubAsset)
301-
return true;
302-
303-
// If we cannot get the path of our reference, we cannot be a persisted asset within an InputActionAsset.
304-
var path = s_GetAssetPath(this);
305-
if (path == null)
306-
return true;
307-
308-
// If we cannot get the main asset we cannot be a persisted asset within an InputActionAsset.
309-
// Also we check that it is the expected type.
310-
var mainAsset = s_LoadMainAssetAtPath(path);
311-
if (!mainAsset)
312-
return true;
313-
314-
// We can only allow setting the reference if it is not part of an persisted InputActionAsset.
315-
return (mainAsset is not InputActionAsset);
316-
}
317-
318-
#endif // UNITY_EDITOR
319262
}
320263
}

0 commit comments

Comments
 (0)