diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 21cddde19e..446a823257 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -18,7 +18,9 @@ however, it has to be formatted properly to pass verification tests. ### Fixed - An issue where a UITK MouseEvent was triggered when changing from Scene View to Game View in the Editor has been fixed. [ISXB-1671](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1671) - Fix documentation error in file AndroidGameController.cs mentioning a wrong controller. [DOCATT-9806] - +- Deferred auto-registration of processors, interactions and composite binding types referenced by `InputActionAsset` + to only happen once when an unresolved type reference is found in an action definition. This avoids reflective + type loading from assemblies for all cases where the Input System is not extended. (ISXB-1766). ## [1.16.0] - 2025-11-10 diff --git a/Packages/com.unity.inputsystem/InputSystem/InputManager.cs b/Packages/com.unity.inputsystem/InputSystem/InputManager.cs index 30649e5269..947bd044a9 100644 --- a/Packages/com.unity.inputsystem/InputSystem/InputManager.cs +++ b/Packages/com.unity.inputsystem/InputSystem/InputManager.cs @@ -1913,9 +1913,9 @@ private void InitializeActions() internal void InitializeData() { m_Layouts.Allocate(); - m_Processors.Initialize(); - m_Interactions.Initialize(); - m_Composites.Initialize(); + m_Processors.Initialize(this); + m_Interactions.Initialize(this); + m_Composites.Initialize(this); m_DevicesById = new Dictionary(); // Determine our default set of enabled update types. By @@ -2026,11 +2026,11 @@ internal void InitializeData() composites.AddTypeRegistration("OneModifier", typeof(OneModifierComposite)); composites.AddTypeRegistration("TwoModifiers", typeof(TwoModifiersComposite)); - // Register custom types by reflection - RegisterCustomTypes(); + // ISXB-1766: Defer loading custom types by reflection unless we have to since referenced from + // .inputaction JSON assets. This is managed via TypeTable.cs. } - void RegisterCustomTypes(Type[] types) + static void RegisterCustomTypes(Type[] types) { foreach (Type type in types) { @@ -2053,8 +2053,18 @@ void RegisterCustomTypes(Type[] types) } } - void RegisterCustomTypes() + private bool m_CustomTypesRegistered; + + internal bool RegisterCustomTypes() { + // If we have already attempted to register custom types, there is no need to reattempt since we + // would end up with the same result again. Only with a domain reload would the resulting types + // be different, and hence it is sufficient to use a static flag that we do not reset. + if (m_CustomTypesRegistered) + return false; // Already evaluated + + m_CustomTypesRegistered = true; + k_InputRegisterCustomTypesMarker.Begin(); var inputSystemAssembly = typeof(InputProcessor).Assembly; @@ -2079,11 +2089,13 @@ void RegisterCustomTypes() } catch (ReflectionTypeLoadException) { - continue; + // Ignore exception } } k_InputRegisterCustomTypesMarker.End(); + + return true; // Signal that custom types were extracted and registered. } internal void InstallRuntime(IInputRuntime runtime) @@ -2164,6 +2176,9 @@ internal void UninstallGlobals() InputControlLayout.s_CacheInstance = default; InputControlLayout.s_CacheInstanceRef = 0; + // Invalidate type registrations + m_CustomTypesRegistered = false; + // Detach from runtime. if (m_Runtime != null) { diff --git a/Packages/com.unity.inputsystem/InputSystem/Utilities/TypeTable.cs b/Packages/com.unity.inputsystem/InputSystem/Utilities/TypeTable.cs index 4120bdce88..009740d344 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Utilities/TypeTable.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Utilities/TypeTable.cs @@ -25,12 +25,16 @@ internal struct TypeTable public HashSet aliases; #endif - public void Initialize() + // Strong coupling to Input Manager which is always the owner + private InputManager m_Manager; + + public void Initialize(InputManager manager) { table = new Dictionary(); #if UNITY_EDITOR aliases = new HashSet(); #endif + m_Manager = manager; } public InternedString FindNameForType(Type type) @@ -80,10 +84,24 @@ public Type LookupTypeRegistration(string name) if (table == null) throw new InvalidOperationException("Input System not yet initialized"); - var internedName = new InternedString(name); - if (table.TryGetValue(internedName, out var type)) - return type; - return null; + return TryLookupTypeRegistration(new InternedString(name)); + } + + private Type TryLookupTypeRegistration(InternedString internedName) + { + if (!table.TryGetValue(internedName, out var type)) + { + // Failed to look-up type, either type do not exist or it is a custom type that has not been registered. + // Check whether we have attempted to load custom types and otherwise lazily load types only when + // relevant and reattempt looking up type by name. (ISXB-1766) + if (m_Manager != null) + { + if (m_Manager.RegisterCustomTypes()) + table.TryGetValue(internedName, out type); + } + } + + return type; } #if UNITY_EDITOR