I wasn’t happy with the specified answers, so I’d like to offer another solution.
Add the following script to any global singleton game object. (I think that’s a common pattern in Unity projects – an empty gameobject at the root level which has no renderer, but contains any scripts intended to be loaded just once, for the whole game/level.)
When tab is pressed, and there is an object already selected, the “next” Selectable GameObject is selected. Now, this is where things get tricky: Unity only gives us the ability to map a “Right”, “Left”, “Up” and “Down” selectable. This is intended to be used with keyboard arrow keys or gamepad arrows, presumably. However, “Tab” behaves a bit differently, generally speaking. It’s USUALLY either “Right” or “Down”, but in certain situations, the next element is something different. For example, in a spreadsheet, “Tab” would usually select the next right element, except when there is no right element, in which case it should select the left-most element on the next row.
Anyways, we don’t handle that complexity in the script below. Fully supporting tab is probably something that Unity should build in, as an additional option to “Right”, “Left”, “Up”, “Down”. We can get 90% of the way there with the heuristic of the “next” tab being “Right”, except when right doesn’t exist, in which case it’s “Down”.
You can set up the Navigation of a Selectable such that the next right/down, or next left/up points to the appropriate element, if you think your users will mostly be using tab and not arrow keys. For my project that makes sense, but it might not make sense for you.
Finally, if there is no object selected when you press Tab, we just select the first selectable object.
Script is here–
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class TabSelect : MonoBehaviour {
private EventSystem eventSystem;
// Use this for initialization
void Start () {
this.eventSystem = EventSystem.current;
}
// Update is called once per frame
void Update () {
// When TAB is pressed, we should select the next selectable UI element
if (Input.GetKeyDown(KeyCode.Tab)) {
Selectable next = null;
Selectable current = null;
// Figure out if we have a valid current selected gameobject
if (eventSystem.currentSelectedGameObject != null) {
// Unity doesn't seem to "deselect" an object that is made inactive
if (eventSystem.currentSelectedGameObject.activeInHierarchy) {
current = eventSystem.currentSelectedGameObject.GetComponent<Selectable>();
}
}
if (current != null) {
// When SHIFT is held along with tab, go backwards instead of forwards
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) {
next = current.FindSelectableOnLeft();
if (next == null) {
next = current.FindSelectableOnUp();
}
} else {
next = current.FindSelectableOnRight();
if (next == null) {
next = current.FindSelectableOnDown();
}
}
} else {
// If there is no current selected gameobject, select the first one
if (Selectable.allSelectables.Count > 0) {
next = Selectable.allSelectables[0];
}
}
if (next != null) {
next.Select();
}
}
}
}