Search Unity

[Solved] Action calls are duplicated "n" times

Discussion in 'Input System' started by NanushTol, Dec 31, 2019.

  1. NanushTol

    NanushTol

    Joined:
    Jan 9, 2018
    Posts:
    131
    Edit: I have solved the issue, he fix is in the next post

    I have a state machine that activate and deactivate action maps,
    when I press the key for the "ShipUI" or "Cancel" actions(lines 33,34 in ShipUIState) the input action is being called the number of times the state/action map has been activated and deactivated.

    to be more clear, if i open and close the ship ui in my game 4 times, the input action will be called 4 times in that point in time and it will call the CloseUI() method 4 times in the same frame, this causes some undesired behavior in other parts of the code.

    Am I doing something wrong when activating and deactivating the action maps in the states Enter() method?
    or this is a bug?
    does anyone has any idea of how to fix this or a workaround for this?

    Ship UI State
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. namespace TheTravler
    7. {
    8.     public class ShipUIState : IState
    9.     {
    10.         public string StateName => "ShipUI";
    11.         public Enums.GameState GameState => Enums.GameState.ShipUI;
    12.  
    13.         GameManager _owner;
    14.         bool SlotActionsActive;
    15.  
    16.  
    17.         public ShipUIState(GameManager owner)
    18.         {
    19.             _owner = owner;
    20.         }
    21.  
    22.         public void Enter()
    23.         {
    24.             Debug.Log("Ship UI State");
    25.  
    26.             Cursor.visible = true;
    27.  
    28.             _owner.InputActions.Disable();
    29.             _owner.InputActions.UI.Enable();
    30.  
    31.             Time.timeScale = 0f;
    32.          
    33.             _owner.InputActions.UI.ShipUI.performed += ctx => CloseUI();
    34.             _owner.InputActions.UI.Cancel.performed += ctx => CloseUI();
    35.  
    36.  
    37.             GameEvents.Instance.OnGeneralSlotUIClickedCallback += SetSlotActionActive;
    38.             GameEvents.Instance.OnCloseSlotActionsUICallback += SetSlotActionUnActive;
    39.         }
    40.  
    41.         public void ExecuteState()
    42.         {
    43.  
    44.         }
    45.  
    46.         public void Exit()
    47.         {
    48.             _owner.InputActions.UI.Disable();
    49.             Time.timeScale = 1f;
    50.         }
    51.  
    52.         private void CloseUI()
    53.         {
    54.             Debug.Log("Close UI");
    55.  
    56.             if (SlotActionsActive)
    57.             {
    58.                 GameEvents.Instance.OnCloseSlotActionsUICallback.Invoke();
    59.             }
    60.             else
    61.             {
    62.                 GameEvents.Instance.OnUiClosedCallback.Invoke();
    63.             }
    64.         }
    65.  
    66.         private void SetSlotActionActive(Item item)
    67.         {
    68.             Debug.Log("Slot Actions Active");
    69.             SlotActionsActive = true;
    70.         }
    71.         private void SetSlotActionUnActive()
    72.         {
    73.             Debug.Log("Slot Actions Not Active");
    74.  
    75.             SlotActionsActive = false;
    76.         }
    77.     }
    78. }

    Flight State (the state that starts after ship ui state has exit)
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. namespace TheTravler
    7. {
    8.     public class FlightState : IState
    9.     {
    10.         public virtual string StateName => "FlightMode";
    11.         public virtual Enums.GameState GameState => Enums.GameState.FlightState;
    12.  
    13.         GameManager _owner;
    14.         public FlightState(GameManager owner)
    15.         {
    16.             _owner = owner;
    17.         }
    18.  
    19.         public virtual void Enter()
    20.         {
    21.             _owner.InputActions.SpaceFlight.Enable();
    22.             Cursor.visible = false;
    23.             Cursor.lockState = CursorLockMode.Locked;
    24.             Debug.Log("Space Flight State");
    25.         }
    26.  
    27.         public virtual void ExecuteState()
    28.         {
    29.  
    30.         }
    31.  
    32.         public virtual void Exit()
    33.         {
    34.             _owner.InputActions.SpaceFlight.Disable();
    35.             Cursor.lockState = CursorLockMode.None;
    36.         }
    37.     }
    38. }
     
    Last edited: Dec 31, 2019
    Inka123 likes this.
  2. NanushTol

    NanushTol

    Joined:
    Jan 9, 2018
    Posts:
    131
    the problem was in lines 33 34, each time the game has entered the state, the state had re-subscribed to the input action, so this was the reason it called the method "n" times.

    I moved line 33 & 34 to the constructor and it fixed the problem

    Fixed code
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. namespace TheTravler
    7. {
    8.     public class ShipUIState : IState
    9.     {
    10.         public string StateName => "ShipUI";
    11.         public Enums.GameState GameState => Enums.GameState.ShipUI;
    12.  
    13.         GameManager _owner;
    14.         bool SlotActionsActive;
    15.  
    16.  
    17.         public ShipUIState(GameManager owner)
    18.         {
    19.             _owner = owner;
    20.  
    21.             _owner.InputActions.UI.ShipUI.performed += ctx => CloseUI();
    22.             _owner.InputActions.UI.Cancel.performed += ctx => CloseUI();
    23.  
    24.             GameEvents.Instance.OnGeneralSlotUIClickedCallback += SetSlotActionActive;
    25.             GameEvents.Instance.OnCloseSlotActionsUICallback += SetSlotActionUnActive;
    26.         }
    27.  
    28.         public void Enter()
    29.         {
    30.             Cursor.visible = true;
    31.  
    32.             _owner.InputActions.Disable();
    33.             _owner.InputActions.UI.Enable();
    34.  
    35.             Time.timeScale = 0f;
    36.          
    37.             Debug.Log("Ship UI State");
    38.         }
    39.  
    40.         public void ExecuteState()
    41.         {
    42.  
    43.         }
    44.  
    45.         public void Exit()
    46.         {
    47.             _owner.InputActions.UI.Disable();
    48.             Time.timeScale = 1f;
    49.         }
    50.  
    51.         private void CloseUI()
    52.         {
    53.             Debug.Log("Close UI");
    54.  
    55.             if (SlotActionsActive)
    56.             {
    57.                 GameEvents.Instance.OnCloseSlotActionsUICallback.Invoke();
    58.             }
    59.             else
    60.             {
    61.                 GameEvents.Instance.OnUiClosedCallback.Invoke();
    62.             }
    63.         }
    64.  
    65.         private void SetSlotActionActive(Item item)
    66.         {
    67.             Debug.Log("Slot Actions Active");
    68.             SlotActionsActive = true;
    69.         }
    70.         private void SetSlotActionUnActive()
    71.         {
    72.             Debug.Log("Slot Actions Not Active");
    73.  
    74.             SlotActionsActive = false;
    75.         }
    76.     }
    77. }