Search Unity

Do I need to remove the performed inputs?

Discussion in 'Input System' started by FlubOtic, Jul 7, 2020.

  1. FlubOtic

    FlubOtic

    Joined:
    Dec 3, 2018
    Posts:
    3
    When I do this:

    Code (CSharp):
    1. void Awake()
    2.     {
    3.         controls = new InputMovement();
    4.         controls.Player.Jump.performed += jum => Jump(jum.ReadValue<float>());
    5.     }
    Do I also have to do this:

    Code (CSharp):
    1. void OnDisable()
    2.     {
    3.         controls.Disable();
    4.         controls.Player.Jump.performed -= jum => Jump(jum.ReadValue<float>());
    5.     }
    Or the second part not needed. Someone said you had to do it or the game would break, but I don't know if I am doing it correctly.
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    No, for sure not like this.

    In general: Yes, you should unregister callbacks to avoid memory leaks.
    But if you do, do it at the right place.
    So either register in Awake and unregister in OnDestroy, or register in OnEnable and unregister in OnDisable.

    However, your code doesn't work, because you are registering an anonymous method (lamda expression) and try to unregister an anonymous method again, but at the place where you unregister it, you are actually creating a new callback, so the removing will fail.

    what you can do is either not using lamda expressions (then your jump method must have a context parameter) or you can simply set the performed event to null, if you are fine that all references are removed.

    Edit: If your input survives the whole game and is not registered a second time, it wouldn't be necessary to unregister.
     
  3. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    If your component is new'ing the generated InputMovement and owning the instance, then no, in general, no cleanup work is necessary.
     
  4. FlubOtic

    FlubOtic

    Joined:
    Dec 3, 2018
    Posts:
    3
    Sorry I am a bit new to unity and C# so I didn't fully understand what you wrote. Is this correct, I move the second one over to OnDestory? I don't really understand what you meant by remove the lambda, could you send me some reference code of it being done correctly.
    1. Code (CSharp):
      1. void Awake()
      2.     {
      3.         controls = new InputMovement();
      4.         controls.Player.Jump.performed += jum => Jump(jum.ReadValue<float>());
      5.     }
      6. void OnDestroy()
      7.     {
      8.         controls.Disable();
      9.         controls.Player.Jump.performed -= jum => Jump(jum.ReadValue<float>());
      10.     }

     
  5. naodisseporfavor

    naodisseporfavor

    Joined:
    Jul 18, 2019
    Posts:
    6
    I found two ways, the first and easy way:
    Assuming, you want to continue using controls, create a method Reset, that will reset the whole controls object:
    Code (CSharp):
    1.    internal void Reset()
    2.     {
    3.         controls.Disable();
    4.         controls = new InputMaster();
    5.         controls.Enable();
    6.     }
    This method is good and fast, but it resets the whole object, not only removing only the method you want to reset.

    The second way is removing only what you want to remove, but it takes a lot of work,
    You can put this performed action into a property of the class, and then you can used it to remove in the OnDestroy.

    Example:
    Code (CSharp):
    1.     private Action<InputAction.CallbackContext> startPressed;
    2.  
    3.     void Start()
    4.     {
    5.         startPressed = context => StartPressed(context);
    6.  
    7.         controls.Player.Start.performed += startPressed;
    8.     }
    9.  
    10.     private void OnDestroy()
    11.     {
    12.         controls.Player.Start.performed -= startPressed;
    13.     }
     
    Last edited: Sep 21, 2023