2
\$\begingroup\$

I have a set of UI buttons in a canvas. The user is be able to navigate the buttons through both mouse clicks and arrow key movements. However, clicking anywhere not on the buttons results in focus being lost from the buttons, making arrow key navigation no longer work. Is there a way to solve this?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Focus is handled by the EventSystem component. While you can’t really do much with that, you can easily replace the existing EventSystem component with your own implementation based on their code. You can find it right here:

https://bitbucket.org/Unity-Technologies/ui/src/0651862509331da4e85f519de88c99d0529493a5/UnityEngine.UI/EventSystem/EventSystem.cs?at=2018.3%2Fstaging&fileviewer=file-view-default

So the first step is to take that file and put it in your project, changing the file name and class name to something like MyEventSystem. Also change the AddComponentEntry attribute argument to something like “Event/My Event System”

Then update the SetSelectedGameObject method to return early if the selected argument is null.

Finally, find the EventSystem GameObject in the scene and replace the EventSystem component on it with your own implementation.

Edit:

Turns out making your own EventSystem won’t work. Instead, you’ll have to create a InputModule implementation. Here’s one:

https://bitbucket.org/Unity-Technologies/ui/src/0651862509331da4e85f519de88c99d0529493a5/UnityEngine.UI/EventSystem/InputModules/PointerInputModule.cs?at=2018.3%2Fstaging&fileviewer=file-view-default

Look into changing DeselectIfSelectionChanged

\$\endgroup\$
2
  • \$\begingroup\$ I am having difficulty implementing this. I ran into a bug involving the RaycasterManager being inaccessible due to its protection level. I also have a bug involving "cannot convert from 'UnityEngine.EventSystems.EventSystem to 'UnityEngine.EventSystems.EventSystem". If I create my own RaycasterManager script the first bug goes away, but I haven't figured out a way to deal with the second one. \$\endgroup\$ Jan 26, 2019 at 3:09
  • 1
    \$\begingroup\$ Whoops. Try my suggested change. \$\endgroup\$
    – Ed Marty
    Feb 1, 2019 at 23:47
3
\$\begingroup\$

What I did to solve this problem was store the last selected object in a gameobject variable and reset it back to that if Eventsystem.current.currentSelectedGameObject returned null:

GameObject lastSelected;

private void Update()
{
    if(EventSystem.current.currentSelectedGameObject == null)
    {
        if (lastSelected && lastSelected.gameObject.activeSelf && lastSelected.GetComponent<Button>() != null && lastSelected.GetComponent<Button>().interactable)
        {
            EventSystem.current.SetSelectedGameObject(lastSelected);
        }            
    }
    else
    {
        lastSelected = EventSystem.current.currentSelectedGameObject;
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .