[Solved] Action calls are duplicated "n" times

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

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace TheTravler
{
    public class ShipUIState : IState
    {
        public string StateName => "ShipUI";
        public Enums.GameState GameState => Enums.GameState.ShipUI;

        GameManager _owner;
        bool SlotActionsActive;


        public ShipUIState(GameManager owner)
        {
            _owner = owner;
        }

        public void Enter()
        {
            Debug.Log("Ship UI State");

            Cursor.visible = true;

            _owner.InputActions.Disable();
            _owner.InputActions.UI.Enable();

            Time.timeScale = 0f;
         
            _owner.InputActions.UI.ShipUI.performed += ctx => CloseUI();
            _owner.InputActions.UI.Cancel.performed += ctx => CloseUI();


            GameEvents.Instance.OnGeneralSlotUIClickedCallback += SetSlotActionActive;
            GameEvents.Instance.OnCloseSlotActionsUICallback += SetSlotActionUnActive;
        }

        public void ExecuteState()
        {

        }

        public void Exit()
        {
            _owner.InputActions.UI.Disable();
            Time.timeScale = 1f;
        }

        private void CloseUI()
        {
            Debug.Log("Close UI");

            if (SlotActionsActive)
            {
                GameEvents.Instance.OnCloseSlotActionsUICallback.Invoke();
            }
            else
            {
                GameEvents.Instance.OnUiClosedCallback.Invoke();
            }
        }

        private void SetSlotActionActive(Item item)
        {
            Debug.Log("Slot Actions Active");
            SlotActionsActive = true;
        }
        private void SetSlotActionUnActive()
        {
            Debug.Log("Slot Actions Not Active");

            SlotActionsActive = false;
        }
    }
}

Flight State (the state that starts after ship ui state has exit)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace TheTravler
{
    public class FlightState : IState
    {
        public virtual string StateName => "FlightMode";
        public virtual Enums.GameState GameState => Enums.GameState.FlightState;

        GameManager _owner;
        public FlightState(GameManager owner)
        {
            _owner = owner;
        }

        public virtual void Enter()
        {
            _owner.InputActions.SpaceFlight.Enable();
            Cursor.visible = false;
            Cursor.lockState = CursorLockMode.Locked;
            Debug.Log("Space Flight State");
        }

        public virtual void ExecuteState()
        {

        }

        public virtual void Exit()
        {
            _owner.InputActions.SpaceFlight.Disable();
            Cursor.lockState = CursorLockMode.None;
        }
    }
}
1 Like

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

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace TheTravler
{
    public class ShipUIState : IState
    {
        public string StateName => "ShipUI";
        public Enums.GameState GameState => Enums.GameState.ShipUI;

        GameManager _owner;
        bool SlotActionsActive;


        public ShipUIState(GameManager owner)
        {
            _owner = owner;

            _owner.InputActions.UI.ShipUI.performed += ctx => CloseUI();
            _owner.InputActions.UI.Cancel.performed += ctx => CloseUI();

            GameEvents.Instance.OnGeneralSlotUIClickedCallback += SetSlotActionActive;
            GameEvents.Instance.OnCloseSlotActionsUICallback += SetSlotActionUnActive;
        }

        public void Enter()
        {
            Cursor.visible = true;

            _owner.InputActions.Disable();
            _owner.InputActions.UI.Enable();

            Time.timeScale = 0f;
          
            Debug.Log("Ship UI State");
        }

        public void ExecuteState()
        {

        }

        public void Exit()
        {
            _owner.InputActions.UI.Disable();
            Time.timeScale = 1f;
        }

        private void CloseUI()
        {
            Debug.Log("Close UI");

            if (SlotActionsActive)
            {
                GameEvents.Instance.OnCloseSlotActionsUICallback.Invoke();
            }
            else
            {
                GameEvents.Instance.OnUiClosedCallback.Invoke();
            }
        }

        private void SetSlotActionActive(Item item)
        {
            Debug.Log("Slot Actions Active");
            SlotActionsActive = true;
        }
        private void SetSlotActionUnActive()
        {
            Debug.Log("Slot Actions Not Active");

            SlotActionsActive = false;
        }
    }
}
1 Like