Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Tab between input fields

Discussion in 'UGUI & TextMesh Pro' started by blitzprog, Aug 22, 2014.

  1. ARares

    ARares

    Joined:
    Mar 18, 2016
    Posts:
    167
    Dude those code are broken, why? well you need to have just the input field, i made my own code which can switch between 2 ore more Inputs Fields.
    Code (CSharp):
    1.     public InputField loginNameField;
    2.     public InputField loginPassField;
    3.  
    4.     private void Update()
    5.     {
    6.         if (Input.GetKeyDown(KeyCode.Tab))
    7.         {
    8.             if (loginNameField.isFocused)
    9.             {
    10.                 EventSystem.current.SetSelectedGameObject(loginPassField.gameObject, null);
    11.                 loginPassField.OnPointerClick(new PointerEventData(EventSystem.current));
    12.             }
    13.  
    14.             if(loginPassField.isFocused)
    15.             {
    16.                 EventSystem.current.SetSelectedGameObject(loginNameField.gameObject, null);
    17.                 loginNameField.OnPointerClick(new PointerEventData(EventSystem.current));
    18.             }
    19.         }
    20.     }
     
    yc960 likes this.
  2. ConflictedDev

    ConflictedDev

    Joined:
    May 19, 2017
    Posts:
    1
    I made an implementation of this myself after needing more than the basic suggestions people have provided - I thought I'd share it here for anyone interested.

    I found:
    • Selectable.allSelectables[0] does NOT always provide the top-most selection
    • Getting the next selectable for a complex layout isn't straight-forward

    I've implemented:
    • A simple sorting method that orders all active selectables based on their X and Y positioning (left-to-right followed by top-to-bottom)
    • A simple, reliable way to navigate forward/backward; includes optional wrap-around to first/last, respectively
    • Navigation with Tab, Enter and Numpad Enter
      (Enter is setup to only work from input fields, where it will also only select the next selection if it is an input field or button)
    • If nothing is selected, the first selectable is selected (Enter is setup to only work if it is an input field or button)
    NOTE: The sorting of selectables is done each time (as this is a simple implementation), you could do this elsewhere when UI elements are enabled/disabled instead.

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.EventSystems;
    4. using UnityEngine.UI;
    5.  
    6. public class UIHotkeySelect : MonoBehaviour
    7. {
    8.     private List<Selectable> m_orderedSelectables;
    9.  
    10.     private void Awake()
    11.     {
    12.         m_orderedSelectables = new List<Selectable>();
    13.     }
    14.  
    15.     private void Update()
    16.     {
    17.         if (Input.GetKeyDown(KeyCode.Tab))
    18.         {
    19.             HandleHotkeySelect(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift), true, false); // Navigate backward when holding shift, else navigate forward.
    20.         }
    21.  
    22.         if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
    23.         {
    24.             HandleHotkeySelect(false, false, true);
    25.         }
    26.     }
    27.  
    28.     private void HandleHotkeySelect(bool _isNavigateBackward, bool _isWrapAround, bool _isEnterSelect)
    29.     {
    30.         SortSelectables();
    31.  
    32.         GameObject selectedObject = EventSystem.current.currentSelectedGameObject;
    33.         if (selectedObject != null && selectedObject.activeInHierarchy) // Ensure a selection exists and is not an inactive object.
    34.         {
    35.             Selectable currentSelection = selectedObject.GetComponent<Selectable>();
    36.             if (currentSelection != null)
    37.             {
    38.                 if (_isEnterSelect)
    39.                 {
    40.                     if (currentSelection.GetComponent<InputField>() != null)
    41.                     {
    42.                         ApplyEnterSelect(FindNextSelectable(m_orderedSelectables.IndexOf(currentSelection), _isNavigateBackward, _isWrapAround));
    43.                     }
    44.                 }
    45.                 else // Tab select.
    46.                 {
    47.                     Selectable nextSelection = FindNextSelectable(m_orderedSelectables.IndexOf(currentSelection), _isNavigateBackward, _isWrapAround);
    48.                     if (nextSelection != null)
    49.                     {
    50.                         nextSelection.Select();
    51.                     }
    52.                 }
    53.             }
    54.             else
    55.             {
    56.                 SelectFirstSelectable(_isEnterSelect);
    57.             }
    58.         }
    59.         else
    60.         {
    61.             SelectFirstSelectable(_isEnterSelect);
    62.         }
    63.     }
    64.  
    65.     ///<summary> Selects an input field or button, activating the button if one is found. </summary>
    66.     private void ApplyEnterSelect(Selectable _selectionToApply)
    67.     {
    68.         if (_selectionToApply != null)
    69.         {
    70.             if (_selectionToApply.GetComponent<InputField>() != null)
    71.             {
    72.                 _selectionToApply.Select();
    73.             }
    74.             else
    75.             {
    76.                 Button selectedButton = _selectionToApply.GetComponent<Button>();
    77.                 if (selectedButton != null)
    78.                 {
    79.                     _selectionToApply.Select();
    80.                     selectedButton.OnPointerClick(new PointerEventData(EventSystem.current));
    81.                 }
    82.             }
    83.         }
    84.     }
    85.  
    86.     private void SelectFirstSelectable(bool _isEnterSelect)
    87.     {
    88.         if (m_orderedSelectables.Count > 0)
    89.         {
    90.             Selectable firstSelectable = m_orderedSelectables[0];
    91.             if (_isEnterSelect)
    92.             {
    93.                 ApplyEnterSelect(firstSelectable);
    94.             }
    95.             else
    96.             {
    97.                 firstSelectable.Select();
    98.             }
    99.         }
    100.     }
    101.  
    102.     private Selectable FindNextSelectable(int _currentSelectableIndex, bool _isNavigateBackward, bool _isWrapAround)
    103.     {
    104.         Selectable nextSelection = null;
    105.  
    106.         int totalSelectables = m_orderedSelectables.Count;
    107.         if (totalSelectables > 1)
    108.         {
    109.             if (_isNavigateBackward)
    110.             {
    111.                 if (_currentSelectableIndex == 0)
    112.                 {
    113.                     nextSelection = (_isWrapAround) ? m_orderedSelectables[totalSelectables - 1] : null;
    114.                 }
    115.                 else
    116.                 {
    117.                     nextSelection = m_orderedSelectables[_currentSelectableIndex - 1];
    118.                 }
    119.             }
    120.             else // Navigate forward.
    121.             {
    122.                 if (_currentSelectableIndex == (totalSelectables - 1))
    123.                 {
    124.                     nextSelection = (_isWrapAround) ? m_orderedSelectables[0] : null;
    125.                 }
    126.                 else
    127.                 {
    128.                     nextSelection = m_orderedSelectables[_currentSelectableIndex + 1];
    129.                 }
    130.             }
    131.         }
    132.  
    133.         return (nextSelection);
    134.     }
    135.  
    136.     private void SortSelectables()
    137.     {
    138.         List<Selectable> originalSelectables = Selectable.allSelectables;
    139.         int totalSelectables = originalSelectables.Count;
    140.         m_orderedSelectables = new List<Selectable>(totalSelectables);
    141.         for (int index = 0; index < totalSelectables; ++index)
    142.         {
    143.             Selectable selectable = originalSelectables[index];
    144.             m_orderedSelectables.Insert(FindSortedIndexForSelectable(index, selectable), selectable);
    145.         }
    146.     }
    147.  
    148.     ///<summary> Recursively finds the sorted index by positional order within m_orderedSelectables (positional order is determined from left-to-right followed by top-to-bottom). </summary>
    149.     private int FindSortedIndexForSelectable(int _selectableIndex, Selectable _selectableToSort)
    150.     {
    151.         int sortedIndex = _selectableIndex;
    152.         if (_selectableIndex > 0)
    153.         {
    154.             int previousIndex = _selectableIndex - 1;
    155.             Vector3 previousSelectablePosition = m_orderedSelectables[previousIndex].transform.position;
    156.             Vector3 selectablePositionToSort = _selectableToSort.transform.position;
    157.  
    158.             if (previousSelectablePosition.y == selectablePositionToSort.y)
    159.             {
    160.                 if (previousSelectablePosition.x > selectablePositionToSort.x)
    161.                 {
    162.                     // Previous selectable is in front, try the previous index:
    163.                     sortedIndex = FindSortedIndexForSelectable(previousIndex, _selectableToSort);
    164.                 }
    165.             }
    166.             else if (previousSelectablePosition.y < selectablePositionToSort.y)
    167.             {
    168.                 // Previous selectable is in front, try the previous index:
    169.                 sortedIndex = FindSortedIndexForSelectable(previousIndex, _selectableToSort);
    170.             }
    171.         }
    172.  
    173.         return (sortedIndex);
    174.     }
    175. }
    176.  
     
    Last edited: Jul 27, 2017
    Andergraw, kryzodoze, Vicomte and 3 others like this.
  3. kzaarka

    kzaarka

    Joined:
    Aug 30, 2017
    Posts:
    1
    Excellent job!!
     
  4. Shinyclef

    Shinyclef

    Joined:
    Nov 20, 2013
    Posts:
    376
    Thanks Kzaarka. I will see how that functionality suits me too :).

    It is mind-boggling how tab and shift-tab is not the default form of navigation, like it is everywhere else.
    "I really want arrow keys to navigate, it's not like I use them to move cursors in input boxes", said no one, ever.
     
    Mikael-H likes this.
  5. MM-Mat

    MM-Mat

    Joined:
    Dec 11, 2015
    Posts:
    2
    Hi,

    Thanks for sharing your script!

    I'm using a modified version of this script and found that it doesn't work for items in an ILayoutGroup, since their reported X and Y coords are the same. For that reason, you might want to add an extra clause in FindSortedIndexForSelectable to compare GetSiblingOrder of the previous and current items in case their coords were the same, as that would fix this edge case.
     
  6. Vicomte

    Vicomte

    Joined:
    Sep 18, 2013
    Posts:
    5
    Thanks a bunch ConflictedDev, this works great, very nice work!
     
  7. kryzodoze

    kryzodoze

    Joined:
    Nov 6, 2013
    Posts:
    17
    Thanks ConflictedDev, that works great.

    For those using his script, you may want to refactor so that SortSelectables() is not getting called everytime a hotkey is pressed. It's a little expensive. You could instead do it in Start() and then again whenever you add/remove UI elements.

    Here's my iteration of the script. I have:
    • Moved SortSelectables() to Start() and made it public
    • Removed 'Enter' functionality because I didn't need it. Sorry :rolleyes:
    • Turned off 'wrap-around' by default. Simply change argument to HandleHotkeySelect().
    • Added a couple comments.
    • Tried to structure code a bit differently to make it easier to understand.
    • Re-formatted the way I like it. Sorry again :rolleyes:
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.EventSystems;
    4. using UnityEngine.UI;
    5.  
    6. public class UITabNavigator : MonoBehaviour
    7. {
    8.     private void Awake()
    9.     {
    10.         this._orderedSelectables = new List<Selectable>();
    11.     }
    12.  
    13.     private void Start()
    14.     {
    15.         this.SortSelectables();
    16.     }
    17.  
    18.     private void Update()
    19.     {
    20.         if (Input.GetKeyDown(KeyCode.Tab))
    21.         {
    22.             // Navigate backward when holding shift, else navigate forward.
    23.             this.HandleHotkeySelect(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift), false);
    24.         }
    25.     }
    26.  
    27.     /// <summary>
    28.     /// Iterates through all selectables in scene and orders them based on their position.
    29.     /// </summary>
    30.     public void SortSelectables()
    31.     {
    32.         List<Selectable> originalSelectables = Selectable.allSelectables;
    33.         int totalSelectables = originalSelectables.Count;
    34.         this._orderedSelectables = new List<Selectable>(totalSelectables);
    35.         for (int index = 0; index < totalSelectables; ++index)
    36.         {
    37.             Selectable selectable = originalSelectables[index];
    38.             this._orderedSelectables.Insert(
    39.                 this.FindSortedIndexForSelectable(index, selectable), selectable);
    40.         }
    41.     }
    42.  
    43.     private void HandleHotkeySelect(bool isNavigateBackward, bool isWrapAround)
    44.     {
    45.         GameObject selectedObject = EventSystem.current.currentSelectedGameObject;
    46.         if (selectedObject != null && selectedObject.activeInHierarchy) // Ensure a selection exists and is not an inactive object.
    47.         {
    48.             Selectable currentSelection = selectedObject.GetComponent<Selectable>();
    49.             if (currentSelection != null)
    50.             {
    51.                 Selectable nextSelection = this.FindNextSelectable(
    52.                     this._orderedSelectables.IndexOf(currentSelection), isNavigateBackward, isWrapAround);
    53.                 if (nextSelection != null)
    54.                 {
    55.                     nextSelection.Select();
    56.                 }
    57.             }
    58.             else
    59.             {
    60.                 this.SelectFirstSelectable();
    61.             }
    62.         }
    63.         else
    64.         {
    65.             this.SelectFirstSelectable();
    66.         }
    67.     }
    68.  
    69.     private void SelectFirstSelectable()
    70.     {
    71.         if (this._orderedSelectables != null && this._orderedSelectables.Count > 0)
    72.         {
    73.             Selectable firstSelectable = this._orderedSelectables[0];
    74.             firstSelectable.Select();
    75.         }
    76.     }
    77.  
    78.     /// <summary>
    79.     /// Looks at ordered selectable list to find the selectable we are trying to navigate to and returns it.
    80.     /// </summary>
    81.     private Selectable FindNextSelectable(int currentSelectableIndex, bool isNavigateBackward, bool isWrapAround)
    82.     {
    83.         Selectable nextSelection = null;
    84.  
    85.         int totalSelectables = this._orderedSelectables.Count;
    86.         if (totalSelectables > 1)
    87.         {
    88.             if (isNavigateBackward)
    89.             {
    90.                 if (currentSelectableIndex == 0)
    91.                 {
    92.                     nextSelection = (isWrapAround) ? this._orderedSelectables[totalSelectables - 1] : null;
    93.                 }
    94.                 else
    95.                 {
    96.                     nextSelection = this._orderedSelectables[currentSelectableIndex - 1];
    97.                 }
    98.             }
    99.             else // Navigate forward.
    100.             {
    101.                 if (currentSelectableIndex == (totalSelectables - 1))
    102.                 {
    103.                     nextSelection = (isWrapAround) ? this._orderedSelectables[0] : null;
    104.                 }
    105.                 else
    106.                 {
    107.                     nextSelection = this._orderedSelectables[currentSelectableIndex + 1];
    108.                 }
    109.             }
    110.         }
    111.  
    112.         return nextSelection;
    113.     }
    114.  
    115.     /// <summary>
    116.     /// Recursively finds the sorted index by positional order within _orderedSelectables (positional order is determined from left-to-right followed by top-to-bottom).
    117.     /// </summary>
    118.     private int FindSortedIndexForSelectable(int selectableIndex, Selectable selectableToSort)
    119.     {
    120.         int sortedIndex = selectableIndex;
    121.         if (selectableIndex > 0)
    122.         {
    123.             int previousIndex = selectableIndex - 1;
    124.             Vector3 previousSelectablePosition = this._orderedSelectables[previousIndex].transform.position;
    125.             Vector3 selectablePositionToSort = selectableToSort.transform.position;
    126.  
    127.             if ((previousSelectablePosition.y < selectablePositionToSort.y)
    128.                 || (previousSelectablePosition.y == selectablePositionToSort.y
    129.                     && previousSelectablePosition.x > selectablePositionToSort.x))
    130.             {
    131.                 // Previous selectable is in front, try the previous index:
    132.                 sortedIndex = this.FindSortedIndexForSelectable(previousIndex, selectableToSort);
    133.             }
    134.         }
    135.  
    136.         return sortedIndex;
    137.     }
    138.  
    139.     private List<Selectable> _orderedSelectables = null;
    140. }
     
    Sssyt likes this.
  8. sarynth

    sarynth

    Joined:
    May 16, 2017
    Posts:
    20
    Urgh... tab should be basic functionality. I also wanted the two most recent UITabNavigators classes to ignore selectables that were on canvas groups that were not interactable. So I had to modify...

    Code (CSharp):
    1.  
    2.         /// <summary>
    3.         /// Iterates through all selectables in scene and orders them based on their position.
    4.         /// </summary>
    5.         public void SortSelectables()
    6.         {
    7.             var originalSelectables = Selectable.allSelectables;
    8.             var totalSelectables = originalSelectables.Count;
    9.             _orderedSelectables = new List<Selectable>(totalSelectables);
    10.             var sortIndex = 0;
    11.             for (var index = 0; index < totalSelectables; ++index)
    12.             {
    13.                 var selectable = originalSelectables[index];
    14.                
    15.                 if (!selectable.IsInteractable()) continue;
    16.                
    17.                 _orderedSelectables.Insert(
    18.                     FindSortedIndexForSelectable(sortIndex, selectable), selectable);
    19.                 sortIndex++;
    20.             }
    21.         }
    22.  
    But, after I did this, they work fabulously! I can suddenly navigate through my form, and was even pleasantly surprised when I was able to tab through the form, past the submit button to my back button, press space bar, and it went back to the previous form. Where I was able to hit tab, get the first element, and tab through to the button to navigate back to my other form.... all with tab and space. Phew.... this was bugging me all evening. Thanks folks.
     
    mandisaw and jj_unity328 like this.
  9. MichiealO

    MichiealO

    Joined:
    Jul 7, 2013
    Posts:
    68
    This is probably necro'ing, but.... if anyone is curious, you would initiate the Move Next code when the user enters the letter. (It's obvious to me, but, since it wasn't obvious to Zealous, I'm stating it here.)
    Unity's EventSystem raises an event on editing the InputField. This allows you to check, validate, etc., the input text in the field. Since Zealous is doing a single character entry per field, it makes sense to just put in the OnValueChanged hook to move to the next field. (See code for when the user presses tab above for actual code.)
     
  10. MichiealO

    MichiealO

    Joined:
    Jul 7, 2013
    Posts:
    68
    Also...
    Unity still hasn't fixed this as of 2018.1...
    But, on a plus side, you can do Photogrammetry like a champ in unity! (Just... hope that you don't need an UI in unity!!! or, other bug fixes...) :p
     
    mandisaw and jj_unity328 like this.
  11. Andergraw

    Andergraw

    Joined:
    Nov 28, 2016
    Posts:
    6
    What a wonderful, neat piece of code.
    Thanks for sharing, it works seamlessly!
    Cheers,
     
  12. jlt

    jlt

    Joined:
    Nov 20, 2014
    Posts:
    1
    I'm using this version, which I modified (from kryzodoze's rev), that uses a list where you set references to Selectables, rather than dynamically try to fetch all Selectables and work out an order based on positioning

    Features:
    - Explict control over tabbing order.
    - Can provide guarantee of existence of selectables (can be wired up statically from Unity or set explicitly from code).
    - Can nest Selectable game objects under KeyboardSelectableGroup and disabling the tree of game objects works as expected (disables that keyboard selectable group).

    Not Features:
    - Does not dynamically detect UI, all references must be set explicitly (either through the Unity editor or code).
    - Having more than 1 keyboard selectable group doesn't work with this snippet (but this could be rewritten to have a group of groups that controls the UI and uses the concatenation of all selectables from groups within the group).

    Code (CSharp):
    1.  
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.EventSystems;
    5. using UnityEngine.UI;
    6.  
    7. public class KeyboardSelectableGroup : MonoBehaviour
    8. {
    9.     public List<Selectable> selectables = new List<Selectable>();
    10.  
    11.     private void Update()
    12.     {
    13.         if (Input.GetKeyDown(KeyCode.Tab))
    14.         {
    15.             // Navigate backward when holding shift, else navigate forward.
    16.             this.HandleHotkeySelect(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift), true);
    17.         }
    18.         if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Return))
    19.         {
    20.             EventSystem.current.SetSelectedGameObject(null, null);
    21.         }
    22.     }
    23.  
    24.     private void HandleHotkeySelect(bool isNavigateBackward, bool isWrapAround)
    25.     {
    26.         GameObject selectedObject = EventSystem.current.currentSelectedGameObject;
    27.         if (selectedObject != null && selectedObject.activeInHierarchy) // Ensure a selection exists and is not an inactive object.
    28.         {
    29.             Selectable currentSelection = selectedObject.GetComponent<Selectable>();
    30.             if (currentSelection != null)
    31.             {
    32.                 Selectable nextSelection = this.FindNextSelectable(
    33.                     selectables.IndexOf(currentSelection), isNavigateBackward, isWrapAround);
    34.                 if (nextSelection != null)
    35.                 {
    36.                     nextSelection.Select();
    37.                 }
    38.             }
    39.             else
    40.             {
    41.                 this.SelectFirstSelectable();
    42.             }
    43.         }
    44.         else
    45.         {
    46.             this.SelectFirstSelectable();
    47.         }
    48.     }
    49.  
    50.     private void SelectFirstSelectable()
    51.     {
    52.         if (selectables != null && selectables.Count > 0)
    53.         {
    54.             Selectable firstSelectable = selectables[0];
    55.             firstSelectable.Select();
    56.         }
    57.     }
    58.  
    59.     /// <summary>
    60.     /// Looks at ordered selectable list to find the selectable we are trying to navigate to and returns it.
    61.     /// </summary>
    62.     private Selectable FindNextSelectable(int currentSelectableIndex, bool isNavigateBackward, bool isWrapAround)
    63.     {
    64.         Selectable nextSelection = null;
    65.  
    66.         int totalSelectables = selectables.Count;
    67.         if (totalSelectables > 1)
    68.         {
    69.             if (isNavigateBackward)
    70.             {
    71.                 if (currentSelectableIndex == 0)
    72.                 {
    73.                     nextSelection = (isWrapAround) ? selectables[totalSelectables - 1] : null;
    74.                 }
    75.                 else
    76.                 {
    77.                     nextSelection = selectables[currentSelectableIndex - 1];
    78.                 }
    79.             }
    80.             else // Navigate forward.
    81.             {
    82.                 if (currentSelectableIndex == (totalSelectables - 1))
    83.                 {
    84.                     nextSelection = (isWrapAround) ? selectables[0] : null;
    85.                 }
    86.                 else
    87.                 {
    88.                     nextSelection = selectables[currentSelectableIndex + 1];
    89.                 }
    90.             }
    91.         }
    92.  
    93.         return nextSelection;
    94.     }
    95.  
    96. }
     
    Last edited: Dec 18, 2018
    antonsem, DustyDev, Zynigma and 5 others like this.
  13. hypernaturalgames

    hypernaturalgames

    Joined:
    Dec 31, 2018
    Posts:
    2
    Works great, thank you
     
  14. injerto

    injerto

    Joined:
    Sep 22, 2019
    Posts:
    6
    Amazing!! Works like charm!!
     
  15. EZaca

    EZaca

    Joined:
    Dec 9, 2017
    Posts:
    15
    While this is a very simple thing to implement by ourselves, I can't think a reason Unity doesn't have it. Is there some technical issue or they just don't want to do that? Even the new Input System has nothing about that.
     
  16. xxShana

    xxShana

    Joined:
    Jul 4, 2019
    Posts:
    21
    Thx ! working well !
     
  17. Zynigma

    Zynigma

    Joined:
    Sep 23, 2012
    Posts:
    22
    Thanks jlt for the final touch on the script, and the rest of you guys. This works great for tabbing between input fields, I only have 11 max input fields on the screen at any time, but you can set the order and go in reverse. Saved me hours of doing it manually for sure...
     
  18. ericspataru

    ericspataru

    Joined:
    Jan 31, 2017
    Posts:
    51
    Thank you for the script. It works wonders!

    Also, could you *pretty please* modify it so it accepts multiple groups?
     
  19. altropetrolio

    altropetrolio

    Joined:
    Nov 8, 2017
    Posts:
    1
    Fantastic! Thank you a lot! Easy to Set and Full Working
     
  20. snowmobeetle

    snowmobeetle

    Joined:
    May 23, 2017
    Posts:
    2
    This gave me a null error when I got to the end of the available selectable objects. I had to add:

    if (system.currentSelectedObject.GetComponent<Selectable>().FindSelectableOnDown() == null) return;

    after the KeyCode.Tab line to prevent the null error.


     
  21. whidzee

    whidzee

    Joined:
    Nov 20, 2012
    Posts:
    126

    Thanks for this mate. It worked an absolute treat
     
unityunity