Search Unity

Custom composite binding in package breaks test in the project that uses it

Discussion in 'Input System' started by ShaneChristopher, Apr 3, 2020.

  1. ShaneChristopher

    ShaneChristopher

    Joined:
    Nov 6, 2018
    Posts:
    12
    Hi,

    I have a Vector2WithOneModifier composite binding written and working correctly in one package, in another package I am using that composite, this works fine when playing in the editor, however when I write a PlayMode test I get the following error:

    Code (CSharp):
    1. InvalidOperationException while resolving binding 'Pan:Vector2WithOneModifier' in action map 'OrbitCameraInputActions (UnityEngine.InputSystem.InputActionAsset):Player'
    2. UnityEngine.InputSystem.PlayerInput:OnEnable() (at Library/PackageCache/com.unity.inputsystem@1.0.0-preview.6/InputSystem/Plugins/PlayerInput/PlayerInput.cs:1548)
    It appears to be an issue with the registration of the binding not being called before the test is run. However tests within the package in which the binding is authored work just fine.

    I have made it work by adding this line before I load the scene in my second packages test:
    Code (CSharp):
    1. InputSystem.RegisterBindingComposite<Vector2WithOneModifier>();
    Obviously this isn't ideal, the custom composite bindings existing registration functions should be called before the tests are run, here custom composite:

    Code (CSharp):
    1. #if UNITY_EDITOR
    2. [InitializeOnLoad]
    3. #endif
    4. [DisplayStringFormat("{firstPart}+{secondPart}")]
    5. public class Vector2WithOneModifier : InputBindingComposite<Vector2>
    6. {
    7.     [InputControl(layout = "Vector2")]
    8.     public int vector2;
    9.  
    10.     [InputControl(layout = "Button")]
    11.     public int modifier;
    12.  
    13. #if UNITY_EDITOR
    14.     static Vector2WithOneModifier()
    15.     {
    16.         Initialize();
    17.     }
    18. #endif
    19.  
    20.     [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    21.     private static void Initialize()
    22.     {
    23.         InputSystem.RegisterBindingComposite<Vector2WithOneModifier>();
    24.     }
    25.  
    26.     public override Vector2 ReadValue(ref InputBindingCompositeContext context)
    27.     {
    28.         bool modifierValue = context.ReadValue<float>(modifier) > float.Epsilon;
    29.         return modifierValue ? context.ReadValue<Vector2, Vector2MagnitudeComparer>(vector2) : Vector2.zero;
    30.     }
    31.  
    32.     public override float EvaluateMagnitude(ref InputBindingCompositeContext context)
    33.     {
    34.         return ReadValue(ref context).magnitude;
    35.     }
    36. }
     
  2. ShaneChristopher

    ShaneChristopher

    Joined:
    Nov 6, 2018
    Posts:
    12
    Bumping this thread for a developer response as this seems to be a bug.
     
  3. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    ATM this is by design. InputTestFixture is meant to put the system in a fully predetermined state. Any additional layout, composite, processor, etc. registrations have to be performed as part of the test setup.

    We have an item in the backlog to revisit how we do registration. I have doubts about the current explicit RegisterXXX approach having been such a great idea overall. Could be we'll switch to an automatic discovery process. Think it'd make sense to also consider at least optionally getting InputTestFixture to pick up everything it can discover.
     
    RaphaelBuquet and ttetrafon like this.