Using .Select() doesn't work for UI Buttons after panel is set inactive then active

I have a pause menu that I am attempting to make work with an Xbox controller. Pressing start will correctly pause the game and reveal the menu, and pressing it once more (or pressing B to cancel) will hide the menu and resume game play.

When I make the pause panel active the first time, it works fine and the first button is in the highlighted state. If I close the pause panel and then reopen it, no highlighted state is shown, but pressing down will correctly highlight the second button. It is almost like if the first button was highlighted when pause was closed, it just doesn’t re-highlight it when it is opened again. If I highlight button 2 before I close the menu (set the panel inactive and resume game play), when I reopen the menu button 1 is correctly highlighted.

Each time I call my function to open the pause menu I am also specifying to select that first button. So, something sort of like this:

function OpenPauseMenu():void
{
     PauseMenu.SetActive(true);
     ResumeButton.Select();
}

Am I missing something simple? Do I need to somehow deselect everything when I close the menu?

Thanks!
Nick

1 Like

I think there is some UI shenanigans that need to be done after it was set active. That or a default element is selected right after you selected your ResumeButton. Have you tried making a delayed function that you invoke?

Invoke(“SelectResumeButton”, 0.1f);

and in that SelectResumeButton function, you call ResumeButton.Select();

Thanks pltremblay, I’ll give that a shot and post how it turns out.

Unfortunately no luck. It still opens up with nothing selected, but then pressing the down arrow or joystick down will highlight the second button, and then I can go back and forth between the two just fine.

Figured out a hack… I created an invisible button so that before I hide my pause panel I call .Select() on it. For some reason, that enables the ResumeButton.Select() to work when I open the pause panel. I couldn’t figure out how to simply deselect the button, which seems like could have solved this problem.

Have you tried setting the EventSystem.current.currentSelectedGameObject to null directly ?

Ok, that looks promising. Now if I could only access that :slight_smile: I am using JS and it gave me an error saying it was read only. Is there something special I need to do to call that? Thanks again for the help!

You’d have to use EventSystem.current.SetSelectedGameObject(…)

Although I don’t see how it would have a different effect. Using .Select() calls SetSelectedGameObject anyways.

Thanks GibTreaty. I am not sure why I can’t figure out how to call this correctly… No matter how I attempt to write it I am not able to reference the event system. I apologize for having so much trouble, typically I can find a good example online somewhere but even looking through all of the manual items about the EventSystem I can’t seem to find the proper way to access it within JS.

what version are you on?

It looks like 5.3.4f1 Personal… To be clear, calling .Select() on my hidden button item did fix the problem, but it seems like de-selecting everything (or setting it null) would be the less hacky way to go about it…

Here is a small section of what I am doing. The “RandomBtn” is the hack that is working, it is just an invisible button I have on the screen that enables me to move the focus off of the button that I really want selected when the pause menu comes back up. I don’t have anything else referencing the EventSystem, and outside of attempting to make it a public GameObject var (which definitely didn’t work) I can’t find the right syntax to use it.

//VARIABLES
public var PauseMenu:GameObject;
public var isPaused:boolean = false;
public var ResumeButton:UI.Button;
public var RandomBtn:UI.Button;

function ResumeGame ()
{
    //UnityEngine.EventSystems.EventSystem.SetSelectedGameObject(null);
    //EventSystemManager.currentSystem.SetSelectedGameObject(null);

    Time.timeScale = 1;
    isPaused = false;
    RandomBtn.Select();
    PauseMenu.SetActive(false); 
}

Ok, the reason why you need to have this delay is because you’re trying to select disabled Button (Child object) from PauseMenu (Parent object). If you would add debug logs for Start() and OnEnable() methods, you would see the order in which they are executed:

  • Parent OnEnable()
  • Parent Start()
  • Child OnEnable()
  • Child Start()

So in Parent’s OnEnable() method the Child object (Button) is not yet enabled.

There is quite easy fix for that:

  1. Create new Script:
private void OnEnable()
{
    EventSystem.current.SetSelectedGameObject(null);
    EventSystem.current.SetSelectedGameObject(gameObject);
}
  1. Assign it to the Button (Child object) that you would like to select when PauseMenu (Parent object) is enabled

That’s all.