# Prevent UI Button focus loss when clicking somewhere else

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?

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

• 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. – super potato Jan 26 '19 at 3:09
• Whoops. Try my suggested change. – Ed Marty Feb 1 '19 at 23:47

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.gameObject.activeSelf && lastSelected.GetComponent<Button>() != null && lastSelected.GetComponent<Button>().interactable)
{
EventSystem.current.SetSelectedGameObject(lastSelected);
}
}
else
{
lastSelected = EventSystem.current.currentSelectedGameObject;
}
}