c# - Unity new input system generating multiple events - Stack Overflow

时间: 2025-01-06 admin 业界

I've just started learning Unity's not-so-new input system. When pressing a button (which causes a UI element to appear and disappear), I'm receiving multiple button press events, which is causing the UI element to flicker (active / inactive) while the user presses the key (for example for a few microseconds). I have been attempting to find a solution that would cause just a single event to be fired regardless of how long the user holds down the key / clicks a button - for example when the key is initially pressed or is released. I have experimented with the Input System Interactions (notably Press: "Release Only" and Tap) but without success - I still get the flickering. I have also been reading about the .WasPerformedThisFrame method, but I can't figure out how to use it.

I've not experienced the same issue with other buttons such as the on-screen movement and jump controls which work fine - possibly because the jump button, for example, only allows a jump to occur if the player isGrounded.

I've been using this tutorial to learn the new input system and so I have set up an input controls asset and have the following code in my InputHandler:

public class InputHandler : MonoBehaviour
{
    [SerializeField] private InputActionAsset inputControls;

    [SerializeField] private string actionMapName = "Unit";
    [SerializeField] private string rollup = "Rollup";

    private InputAction rollupAction;

    public bool RollupTriggered { get; private set; }

    public static InputHandler Instance {get; private set; }

    private void Awake()
        {
            ...
            rollupAction = inputControls.FindActionMap(actionMapName).Find(rollup);
            RegisterInputActions();
        }

    void RegisterInputActions()
    {
        ...
        rollupAction.performed += context => RollupTriggered = true;
        rollupAction.canceled += context => RollupTriggered = false;
    }

    private void OnEnable()
    {
        ...
        rollupAction.Enable();
    }

    private void OnDisable()
    {
        ...
        rollupAction.Disable();
    }
}

Then, in my player / UI controller script, I have the following:

public class UnitController : MonoBehaviour
{
    private InputHandler inputHandler;
    public GameObject hudPanel;

    void Update()
    {
        ...
        ShowHideHUD();
    }

    void ShowHideHUD()
    {
        if (inputHandler.RollupTriggered)
        {
            if (hudPanel.activeSelf)
            {
                hudPanel.SetActive(false);
            }
            else
            {
                hudPanel.SetActive(true);
            }
        }
    }
}

I've just started learning Unity's not-so-new input system. When pressing a button (which causes a UI element to appear and disappear), I'm receiving multiple button press events, which is causing the UI element to flicker (active / inactive) while the user presses the key (for example for a few microseconds). I have been attempting to find a solution that would cause just a single event to be fired regardless of how long the user holds down the key / clicks a button - for example when the key is initially pressed or is released. I have experimented with the Input System Interactions (notably Press: "Release Only" and Tap) but without success - I still get the flickering. I have also been reading about the .WasPerformedThisFrame method, but I can't figure out how to use it.

I've not experienced the same issue with other buttons such as the on-screen movement and jump controls which work fine - possibly because the jump button, for example, only allows a jump to occur if the player isGrounded.

I've been using this tutorial to learn the new input system and so I have set up an input controls asset and have the following code in my InputHandler:

public class InputHandler : MonoBehaviour
{
    [SerializeField] private InputActionAsset inputControls;

    [SerializeField] private string actionMapName = "Unit";
    [SerializeField] private string rollup = "Rollup";

    private InputAction rollupAction;

    public bool RollupTriggered { get; private set; }

    public static InputHandler Instance {get; private set; }

    private void Awake()
        {
            ...
            rollupAction = inputControls.FindActionMap(actionMapName).Find(rollup);
            RegisterInputActions();
        }

    void RegisterInputActions()
    {
        ...
        rollupAction.performed += context => RollupTriggered = true;
        rollupAction.canceled += context => RollupTriggered = false;
    }

    private void OnEnable()
    {
        ...
        rollupAction.Enable();
    }

    private void OnDisable()
    {
        ...
        rollupAction.Disable();
    }
}

Then, in my player / UI controller script, I have the following:

public class UnitController : MonoBehaviour
{
    private InputHandler inputHandler;
    public GameObject hudPanel;

    void Update()
    {
        ...
        ShowHideHUD();
    }

    void ShowHideHUD()
    {
        if (inputHandler.RollupTriggered)
        {
            if (hudPanel.activeSelf)
            {
                hudPanel.SetActive(false);
            }
            else
            {
                hudPanel.SetActive(true);
            }
        }
    }
}
Share Improve this question asked 14 hours ago MuppetDanceMuppetDance 16411 bronze badges 4
  • any chance your register actions are being redone, when they dont get undone ? so, for example, if Inputhandler is on a donotdestroy, and you add to it each time you load a level.. – BugFinder Commented 2 hours ago
  • I've only got the one level / screen, so unlikely, though I am not explicitly unlistening to the events, which for memory management, I ought really to do. – MuppetDance Commented 2 hours ago
  • could still apply, if you reload the screen and use donotestroy at some point.. – BugFinder Commented 2 hours ago
  • Well I doubt the event is triggered twice .. but there is nothing in your code preventing the same (inputHandler.RollupTriggered) be true across multiple consequent frames ... – derHugo Commented 1 hour ago
Add a comment  | 

1 Answer 1

Reset to default 0

I've implemented a solution, but it's a bit janky and there must be a better way!

The player / UI control script now reads:

public class UnitController : MonoBehaviour
{
    private InputHandler inputHandler;
    public GameObject hudPanel;

    private bool rollupPressed = false;

    void Update()
    {
        ...
        ShowHideHUD();
    }

    void ShowHideHUD()
    {
        if (inputHandler.RollupTriggered)
        {
            rollupPressed = true;
        }

        if (rollupPressed && !inputHandler.RollupTriggered)
        {
            rollupPressed = false;
            if (hudPanel.activeSelf)
            {
                hudPanel.SetActive(false);
            }
            else
            {
                hudPanel.SetActive(true);
            }
        }
    }
}