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?
2 Answers
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:
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:
Look into changing DeselectIfSelectionChanged
-
\$\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
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;
}
}