Skip to content

Commit 7c5305a

Browse files
committed
FIX: RemoveActionMap does not remove contained actions. Additional bug fixing of InputActionReference, added more tests.
1 parent 27b0311 commit 7c5305a

File tree

3 files changed

+57
-11
lines changed

3 files changed

+57
-11
lines changed

Assets/Tests/InputSystem/CoreTests_Actions_Reference.cs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
using System;
12
using NUnit.Framework;
23
using UnityEngine;
34
using UnityEngine.InputSystem;
5+
using Object = System.Object;
46

57
partial class CoreTests
68
{
@@ -95,8 +97,10 @@ public void Actions_Reference_CanResolveActionAfterReassignment()
9597
Assert.That(reference.ToString(), Is.EqualTo(":map2/action3"));
9698
}
9799

98-
[Test]
99-
public void Actions_Reference_NameShouldReflectReferencedAction()
100+
[TestCase(typeof(InputAction))]
101+
[TestCase(typeof(InputActionMap))]
102+
[TestCase(typeof(InputActionAsset))]
103+
public void Actions_Reference_NameShouldReflectReferencedAction(Type typeToDelete)
100104
{
101105
var map = new InputActionMap("map");
102106
var action1 = map.AddAction("action1");
@@ -112,15 +116,34 @@ public void Actions_Reference_NameShouldReflectReferencedAction()
112116
Assert.That(reference.ToDisplayName(), Is.EqualTo("map/action1"));
113117
Assert.That(reference.ToString(), Is.EqualTo(":map/action1"));
114118

115-
// Delete the referenced action
116-
117-
asset.RemoveAction("map/action1");
119+
// Delete the referenced action directly or indirectly
120+
if (typeToDelete == typeof(InputAction))
121+
asset.RemoveAction("map/action1");
122+
else if (typeToDelete == typeof(InputActionMap))
123+
asset.RemoveActionMap("map");
124+
else if (typeToDelete == typeof(InputActionAsset))
125+
UnityEngine.Object.DestroyImmediate(asset);
118126

119127
// TODO reference need to react to this
120-
Assert.That(reference.action, Is.SameAs(action1));
128+
Assert.That(reference.action, Is.Null);
121129
Assert.That(reference.asset, Is.SameAs(asset));
122130
Assert.That(reference.name, Is.EqualTo("map/action1")); // Unexpected when no longer existing
123131
Assert.That(reference.ToDisplayName(), Is.EqualTo("map/action1")); // Unexpected when no longer existing
124-
Assert.That(reference.ToString(), Is.EqualTo(":map/action1")); // Unexpected when no longer existing
132+
//Assert.That(reference.ToString(), Is.EqualTo(":" + new Guid(action1.m_Id))); // Unexpected when no longer existing
125133
}
134+
135+
// List of bugs addressed on this branch:
136+
// (FIXED) InputActionReference - Do not set m_Action when calling Set.
137+
// (FIXED) InputActionReference.asset - Returns incorrect asset after being .Set if .action is called before Set.
138+
// (FIXED) InputActionReference - Assigned with Set during play-mode corrupts InputActionAsset by mutating asset reference into pointing into potentially another asset and overwrites existign asset.
139+
// (FIXED) InputActionReferencePropertyDrawer - Assigns direct reference into InputActionAsset to InputActionReference fields leading to corruption.
140+
// InputActionReference - Contains stale reference and looks like a valid reference if the action is deleted. .action returns removed action.
141+
// InputActionReference - Do not invalidate if action, action map or asset is deleted/destroyed. .action still returns the action.
142+
// (FIXED) InputActionAsset.RemoveActionMap - Do not remove actions within the map and they keep a stale reference to the removed map.
143+
// (FIXED) InputActionAsset.RemoveAction - Throws exception if action do not have any bindings.
144+
145+
146+
// TODO Make a test where action map is deleted
147+
// TODO Make a test where asset is deleted
148+
// TODO Make an undo resolve test
126149
}

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

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,12 @@ public InputAction action
5353
{
5454
get
5555
{
56-
if (m_Action != null)
56+
// Note that we check m_Action since it would be null if we haven't yet resolved the action.
57+
// We also need to check that m_Action.actionMap isn't null since it would be null if the
58+
// action was deleted.
59+
if (m_Action != null && m_Action.actionMap != null && m_Asset)
5760
return m_Action;
58-
if (!m_Asset)
59-
return null;
60-
return (m_Action = m_Asset.FindAction(new Guid(m_ActionId)));;
61+
return (m_Action = ResolveAction());
6162
}
6263
}
6364

@@ -236,5 +237,20 @@ public InputAction ToInputAction()
236237
{
237238
return action;
238239
}
240+
241+
private InputAction ResolveAction()
242+
{
243+
return m_Asset == null ? null : m_Asset.FindAction(new Guid(m_ActionId));
244+
}
245+
246+
// OnValidate() is stripped out from player builds (editor only).
247+
/*private void OnValidate()
248+
{
249+
var resolvedAction = ResolveAction();
250+
if (resolvedAction == null)
251+
{
252+
Debug.Log("RESOLVED TO NULL");
253+
}
254+
}*/
239255
}
240256
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ public static void RemoveActionMap(this InputActionAsset asset, InputActionMap m
104104
if (map.m_Asset != asset)
105105
return;
106106

107+
// First remove all actions from map (They become "singleton actions" or may get collected if not referenced).
108+
if (map.m_Actions != null)
109+
{
110+
for (var i = map.m_Actions.Length - 1; i >= 0; --i)
111+
RemoveAction(map.m_Actions[i]);
112+
}
113+
107114
ArrayHelpers.Erase(ref asset.m_ActionMaps, map);
108115
map.m_Asset = null;
109116
asset.OnSetupChanged();

0 commit comments

Comments
 (0)