Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Newly active button receives OnClick() for the same button press that made it active.

Discussion in 'UGUI & TextMesh Pro' started by DimBimbleby, Feb 29, 2024.

  1. DimBimbleby

    DimBimbleby

    Joined:
    Dec 5, 2023
    Posts:
    6
    This problem is kind of hard to explain, but it must be a very common pattern in Unity UI development and I'm curious how people avoid it. Please bear with me and I'll try make the problem clear.

    Let's say that you have a main menu with a "Play" button and an "Options" button.

    The "Options" button has an OnClick handler (in the editor, not in code) that references a certain panel and calls SetActive(true) on that panel. In other words, it opens the Options panel.

    The other thing the Options button does is to set the Play button either as non-active or as non-interactable (depending on whether you want it to still show or not). You do this so that when the player is using a gamepad to move between available controls, the EventSystem does not take them to the Play button (which might be hidden behind the Options panel anyway, and therefore confusing).

    So you've brought up the Options panel and hidden or disabled the Play button.

    The Options panel has various controls. One of them is a Close button. If you click the Close button, its OnClick handlers (in the editor) say to set the Options panel as inactive and to re-enable the Play button. It also sets the Play button as current (Button.Select()).

    With the mouse, this works fine. You click the Close button, the Options panel closes, the Play button is enabled and selected. All good.

    But if you hit the Enter key (mapped to "Submit") to trigger the Close button, a problem occurs.

    The Close button correctly hides the Options panel, shows the Play button, and selects the Play button. But for some reason, now that the Play button is the "current" button, it also receives the message to Submit. It's as if the Enter key has triggered both the Close button and the Play button at the same time.

    This is an extremely, extremely common pattern in UI (open a panel, close a panel, disable or ignore buttons in the outer context while it's open). How do you implement it in Unity?

    Naturally you can throw code at the problem. You can, for example, create a Coroutine to make a little delay between the closing of the Options panel and the selection of the Play button. That solves the problem. But it's clunky, and it's a hack, especially when you're needing to do this for every panel in a UI system.

    What am I missing? How do you build panels in basic Unity—preferably with no additional code—that know how to enable and disable the right buttons at the right times?