UI Menu not starting with a highlighted button

Hi,

Issue: When my Main Menu comes up on screen there is no default button highlighted. Once I use a key to move down to another button, that button highlights correctly.

Need: I need to be able to have the menu start with a highlighted button.

So far I have tried simple stuff such as adding a script to the default button which on awake has ‘ButtonRef.Select();’

That did not work, so I have also tried more odd things through the event system such as ‘ExecuteEvents.Execute(this.gameObject, be, ExecuteEvents.selectHandler);’ or
‘ExecuteEvents.Execute(this.gameObject, pointer, ExecuteEvents.pointerEnterHandler);’

Still, none of the buttons are highlighted. I have also watched many UI tutorials, but when they run their games their menus do not have a default highlighted button either. That is ok for tablet, but not for my PC game which will be using keyboard and joystick.

Thanks
DaVoodoochief

In your event system you can set the first selected object. If this alone doesn’t give you your desired results then the next thing you can do is add an event trigger to your objects and add an event for when it’s selected so it highlights itself. That should fix it for sure.

2 Likes

Hi QuaintShanty,
Thanks for the reply, I have already tried the first selected with this code.

EVRef.firstSelectedGameObject = this.gameObject;
EVRef.SetSelectedGameObject(this.gameObject);

Alas this doesn’t appear to make any difference, though I thought it would have.

As for your second suggestion. I have tried using an Event Trigger to activate the highlight, but there seems to be so many options and the several I have tried make no difference.

e.g.
BaseEventData be = new BaseEventData(EventSystem.current);
ExecuteEvents.Execute(this.gameObject, be, ExecuteEvents.selectHandler);

I am open to any more suggestions/work arounds.

One thing I cannot get to happen is to trigger an event in code to simulate a ‘downArrow’ as I think that would highlight the second button on the screen (which would be fine as a work around for me). So if anyone knows how to do that, I would appreciate it. I have spent way too many hours playing with this, but I do feel this needs to work before I go full Joystick control.

DaVoodoochief

My Answer… Hack really.

I have come up with a work around for this bug/lackOfFeature. It is AOK for the buttons to work this way for tablets where no default button is set, but not for the console style I am going for.

Anyway, back to the hack.

void OnEnbale() {
   EventSystem EVRef = EventSystem.current; // get the current event system
   EVRef.SetSelectedGameObject(this.gameObject);   // set current selected button
   //    Hack: Move up to the button above us (so we can hack a highlight on it)
   Button bref = EVRef.currentSelectedGameObject.GetComponent<Button>();
   EVRef.SetSelectedGameObject(bref.navigation.selectOnUp.gameObject, null);
}

That above works because I put the script on the SECOND button in the Menu. This is in the OnEnable() function and when I activate this Menu this code is run and it sets the current game object to this second button, then immediately uses the Button Navigation references to move UP, to the top button in my menu.
To make this work you will also need to ‘Explicity’ set the button navigation values. Which is easy in the editor as it is drag and drop.

I have already extended this to use my Joystick input to move around the buttons as well.

I hope this is helpful to anyone else looking for a light weight hack.

DaVoodoochief

@Voodoochief

Hi,
“So far I have tried simple stuff such as adding a script to the default button which on awake has ‘ButtonRef.Select();’”

did you try Start instead of Awake?

IIRC, using button.Select() in Start works just fine?

Hi,
i think that’s because once you have selected an object the EventSystem keeps that object selected until you select something else. So it only transitions once to the its selected state. Just deselect everything using
EventSystem.current.SetSelectedGameObject(null)
before calling select on your default element to force the transition again.

3 Likes

Thanks! Thats what i needed

Just FYI for anyone still fiddling with this, it is sometimes common for people to disable a parent object prior to “selecting/deselecting” the button to be highlighted when the menu is presented.
Here is a snippet of code that shows the proper order of “selecting vs enabling a parent canvas”:

   void ToggleMenuActive()
    {
        if (!MainMenuCanvas.activeInHierarchy)
        {
            MainMenuCanvas.SetActive(!MainMenuCanvas.activeInHierarchy);
            if(EventSystem.current != null && FirstSelectedObject != null)
            {
                EventSystem.current.SetSelectedGameObject(FirstSelectedObject);                        
            }
            //Don't do this:
            //if (EventSystem.current != null && FirstSelectedObject != null)
            //{
            //    EventSystem.current.SetSelectedGameObject(FirstSelectedObject);
            //}
            //MainMenuCanvas.SetActive(!MainMenuCanvas.activeInHierarchy);

            Time.timeScale = 0.0f;
        }
        else
        {
            EventSystem.current.SetSelectedGameObject(null);
            MainMenuCanvas.SetActive(!MainMenuCanvas.activeInHierarchy);
            //Don't do this:
            //MainMenuCanvas.SetActive(!MainMenuCanvas.activeInHierarchy);
            //EventSystem.current.SetSelectedGameObject(null);

           Time.timeScale = OriginalTimeScale;
        }
    }

The idea being that you want to “enable” any parent canvas/object to the buttons prior to setting the button in question as being selected.
So the things not to do:

  • setting your button object as selected prior to enabling the parent canvas (it will not highlight).
  • disabling your parent canvas prior to “deselecting all” (i.e. null) will present the bug of not properly highlighting the 2nd time you toggle/activate your menu because the event system still thinks the button is highlighted.

The main idea being:
Make sure the parent to your buttons (typically people use a canvas) is active while selecting/deselecting buttons otherwise the messages will get dropped and not processed by the event system.

As an ancillary, the above code pauses the game too (you just need to store the “float OriginalTimeScale” off at the start so it can be set back to what it was in the first place when resuming the game).
Cheers

4 Likes