Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by CareXish · Sep 04, 2014 at 04:10 AM · uiselecting objects

4.6 uGUI select next InputField with Enter/tab

I've been trying to make a login screen. ( just for practice ). But I dont know how to 'select' the password InputField when you press enter or tab at the username InputField.

I did however add a listener. This listener actually gets the value of the InputField and puts it in a variable. Thats all fine, but after that it should go to the Password InputField. But it doesn't do that.

How can I do that?

Also, once you've entered your password, and deselect the InputField, it shows the value of the password. No * whatsoever. Is this a bug or am I doing something wrong?

*C# is preferred.

Thanks in advance!

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

5 Replies

· Add your reply
  • Sort: 
avatar image
10
Wiki

Answer by aeasterling · May 31, 2015 at 11:44 AM

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();
             }
         }
     }
 }
 


[1]: /storage/temp/47344-screen-shot-2015-05-30-at-31648-pm.png

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image addy55 · Sep 11, 2015 at 06:36 AM 0
Share

Works like a Charm!! Thanks for this handy script. :)

avatar image splas_boomerang · Dec 21, 2016 at 10:46 AM 0
Share

Thank you for your great code! And, I think you should add this code at 42 line to back to the first selectable object.

                 if (next == null)
                 {
                     next = Selectable.allSelectables[0];
                 }
avatar image
1

Answer by sed · Dec 11, 2014 at 03:46 PM

As of 4.6.1: Attach this script to your Input Field. Also to show '*' you have to set the "Content Type" to password. To navigate using 'Enter' set EndEdit handler (in editor) to the next input fields Select method.

 using UnityEngine;
 using System.Collections;
 using UnityEngine.UI;
 using UnityEngine.EventSystems;
 
 public class InputFieldNavigation : MonoBehaviour {
 
     public enum NavigationDirection { Down, Up, };
 
     public NavigationDirection Direction;
 
     private EventSystem system;
 
     void Start ()
     {
         system = EventSystem.current;
     }
     
     public void Update()
     {
         if (Input.GetKeyDown(KeyCode.Tab) && system.currentSelectedGameObject == gameObject)
         {
 
             Selectable next = null;
 
             if(Direction == NavigationDirection.Down)
             {
                 next = system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnDown();
             }
             else 
             {
                 next = system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnUp();
             }
 
             if (next!= null) 
             {
                 system.SetSelectedGameObject(next.gameObject);
                 next.Select();
                 var field = next as InputField;
                 if(field != null) field.OnPointerClick(new PointerEventData(system));
             }
             //else Debug.Log("next nagivation element not found");
             
         }
     }
 }


I expanded on the idea presented here: http://forum.unity3d.com/threads/tab-between-input-fields.263779/

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image aeasterling · May 30, 2015 at 09:29 PM 0
Share

In Unity 5, this portion doesn't seem to be necessary --

 if (field != null) field.OnPointerClick(new PointerEventData(eventSystem));

Focus is properly passed to text fields with SetSelectedGameObject(). Perhaps this was needed in 4.6, maybe? For Unity 5, SetSelectedGameObject() works just fine.

avatar image aeasterling · May 30, 2015 at 09:34 PM 1
Share

I'm not super happy with the top comment here. You have to add it every single UI element in your game, which to me seems super error prone. (What if you forget to add it on a UI element? Suddenly tab won't work.)

Furthermore, I'm a little confused about the "direction" property -- it doesn't seem to be useful. Why would you want tab to go backwards ins$$anonymous$$d of forward?

Also, there's no support for SHIFT, which seems like something you'd want. I often use Shift+Tab to move between elements.

Also, you have to actually give initial focus to an element for this script to take over. That is, if you load up a UI and don't give initial focus to something, the user would have to click on something to let tab take over. However, one would expect that pressing tab with no focus would go ahead and select the next selectable element. (This is how browsers work for example.)

I've offered another solution below--

avatar image
1

Answer by jessejarvis · Oct 14, 2016 at 06:42 PM

Okay. So, NONE of this worked for me so I scripted my own.

Setup Instructions: Drag script on any game object (For me I did the "Login Window" in my Canvas. Once the script is in your scene, set NavFields to the size of the fields you want and drag in your GameObjects. This allows tab navigation between any game objects, I personally use this to tab between Username, password, and other buttons I have.

Enjoy!

 using UnityEngine;
 using System.Collections;
 using UnityEngine.UI;
 using UnityEngine.EventSystems;
 
 public class SLINavigateInputFields : MonoBehaviour
 {
     public GameObject[] navFields;
     private int selected;
     private int maxArray;
     private GameObject currentSelected;
 
     void Start()
     {
         selected = 0;
         maxArray = navFields.Length -1;
         currentSelected = navFields[selected].gameObject;
     }
 
     void Update()
     {
         if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.Tab))
         {
             if (selected > 0)
             {
                 selected--;
                 currentSelected = navFields[selected].gameObject;
 
                 if (EventSystem.current == null)
                     return;
                 EventSystem.current.SetSelectedGameObject(currentSelected);
                 if (GetComponent<InputField>() != null)
                 {
                     GetComponent<InputField>().Select();
                     GetComponent<InputField>().ActivateInputField();
                 }
             }
         }
         else if (Input.GetKeyDown(KeyCode.Tab))
         {
             if (selected < maxArray)
             {
                 selected++;
                 currentSelected = navFields[selected].gameObject;
 
                 if (EventSystem.current == null)
                     return;
                 EventSystem.current.SetSelectedGameObject(currentSelected);
                 if (GetComponent<InputField>() != null)
                 {
                     GetComponent<InputField>().Select();
                     GetComponent<InputField>().ActivateInputField();
                 }
             }
         }
     }
 }
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Lucas_Gaspar · Mar 13, 2019 at 05:24 AM 0
Share

Thank you! I was thinking on doing something like this

avatar image
0

Answer by JITENDRA-RAJ · Sep 04, 2014 at 07:02 AM

For select Next filed use SetNextControlName .

  GUI.SetNextControlName("loginUsername");
                 GUILayout.BeginArea (new Rect (100, 186, 199, 63));
                 loginUsername = GUILayout.TextField(loginUsername, login_txt.customStyles[0],GUILayout.Height(30));//,GUILayout.MaxWidth(200),GUILayout.MaxHeight(23));    
                 GUILayout.EndArea ();
                 GUI.SetNextControlName("loginPassword ");
                 if (GUI.GetNameOfFocusedControl () == string.Empty) {
                         GUI.FocusControl ("loginUsername");
                 } 
     GUILayout.BeginArea (new Rect (100, 230, 199, 63));
             loginPassword = GUILayout.PasswordField(loginPassword, '*',UIManager.instance.login_txt.customStyles[0],GUILayout.Height(30));
             GUILayout.EndArea ();
 






Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image JamieFristrom · Apr 17, 2015 at 08:51 PM 1
Share

I believe the OP was about the new Unity GUI system.

avatar image
0

Answer by ConflictedDev · Jul 26, 2017 at 09:01 PM

I hate to add to the implementations already provided but 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

  • None of the above include navigation with the Enter key

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.

 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.EventSystems;
 using UnityEngine.UI;
 
 public class UIHotkeySelect : MonoBehaviour
 {
     private List<Selectable> m_orderedSelectables;
 
     private void Awake()
     {
         m_orderedSelectables = new List<Selectable>();
     }
 
     private void Update()
     {
         if (Input.GetKeyDown(KeyCode.Tab))
         {
             HandleHotkeySelect(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift), true, false); // Navigate backward when holding shift, else navigate forward.
         }
 
         if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
         {
             HandleHotkeySelect(false, false, true);
         }
     }
 
     private void HandleHotkeySelect(bool _isNavigateBackward, bool _isWrapAround, bool _isEnterSelect)
     {
         SortSelectables();
 
         GameObject selectedObject = EventSystem.current.currentSelectedGameObject;
         if (selectedObject != null && selectedObject.activeInHierarchy) // Ensure a selection exists and is not an inactive object.
         {
             Selectable currentSelection = selectedObject.GetComponent<Selectable>();
             if (currentSelection != null)
             {
                 if (_isEnterSelect)
                 {
                     if (currentSelection.GetComponent<InputField>() != null)
                     {
                         ApplyEnterSelect(FindNextSelectable(m_orderedSelectables.IndexOf(currentSelection), _isNavigateBackward, _isWrapAround));
                     }
                 }
                 else // Tab select.
                 {
                     Selectable nextSelection = FindNextSelectable(m_orderedSelectables.IndexOf(currentSelection), _isNavigateBackward, _isWrapAround);
                     if (nextSelection != null)
                     {
                         nextSelection.Select();
                     }
                 }
             }
             else
             {
                 SelectFirstSelectable(_isEnterSelect);
             }
         }
         else
         {
             SelectFirstSelectable(_isEnterSelect);
         }
     }
 
     ///<summary> Selects an input field or button, activating the button if one is found. </summary>
     private void ApplyEnterSelect(Selectable _selectionToApply)
     {
         if (_selectionToApply != null)
         {
             if (_selectionToApply.GetComponent<InputField>() != null)
             {
                 _selectionToApply.Select();
             }
             else
             {
                 Button selectedButton = _selectionToApply.GetComponent<Button>();
                 if (selectedButton != null)
                 {
                     _selectionToApply.Select();
                     selectedButton.OnPointerClick(new PointerEventData(EventSystem.current));
                 }
             }
         }
     }
 
     private void SelectFirstSelectable(bool _isEnterSelect)
     {
         if (m_orderedSelectables.Count > 0)
         {
             Selectable firstSelectable = m_orderedSelectables[0];
             if (_isEnterSelect)
             {
                 ApplyEnterSelect(firstSelectable);
             }
             else
             {
                 firstSelectable.Select();
             }
         }
     }
 
     private Selectable FindNextSelectable(int _currentSelectableIndex, bool _isNavigateBackward, bool _isWrapAround)
     {
         Selectable nextSelection = null;
 
         int totalSelectables = m_orderedSelectables.Count;
         if (totalSelectables > 1)
         {
             if (_isNavigateBackward)
             {
                 if (_currentSelectableIndex == 0)
                 {
                     nextSelection = (_isWrapAround) ? m_orderedSelectables[totalSelectables - 1] : null;
                 }
                 else
                 {
                     nextSelection = m_orderedSelectables[_currentSelectableIndex - 1];
                 }
             }
             else // Navigate forward.
             {
                 if (_currentSelectableIndex == (totalSelectables - 1))
                 {
                     nextSelection = (_isWrapAround) ? m_orderedSelectables[0] : null;
                 }
                 else
                 {
                     nextSelection = m_orderedSelectables[_currentSelectableIndex + 1];
                 }
             }
         }
 
         return (nextSelection);
     }
 
     private void SortSelectables()
     {
         List<Selectable> originalSelectables = Selectable.allSelectables;
         int totalSelectables = originalSelectables.Count;
         m_orderedSelectables = new List<Selectable>(totalSelectables);
         for (int index = 0; index < totalSelectables; ++index)
         {
             Selectable selectable = originalSelectables[index];
             m_orderedSelectables.Insert(FindSortedIndexForSelectable(index, selectable), selectable);
         }
     }
 
     ///<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>
     private int FindSortedIndexForSelectable(int _selectableIndex, Selectable _selectableToSort)
     {
         int sortedIndex = _selectableIndex;
         if (_selectableIndex > 0)
         {
             int previousIndex = _selectableIndex - 1;
             Vector3 previousSelectablePosition = m_orderedSelectables[previousIndex].transform.position;
             Vector3 selectablePositionToSort = _selectableToSort.transform.position;
 
             if (previousSelectablePosition.y == selectablePositionToSort.y)
             {
                 if (previousSelectablePosition.x > selectablePositionToSort.x)
                 {
                     // Previous selectable is in front, try the previous index:
                     sortedIndex = FindSortedIndexForSelectable(previousIndex, _selectableToSort);
                 }
             }
             else if (previousSelectablePosition.y < selectablePositionToSort.y)
             {
                 // Previous selectable is in front, try the previous index:
                 sortedIndex = FindSortedIndexForSelectable(previousIndex, _selectableToSort);
             }
         }
 
         return (sortedIndex);
     }
 }







Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

12 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How do I move a clicked and selected object to a clicked position 1 Answer

uGUI: Choose parent for anchors 0 Answers

uGUI text field set focus 0 Answers

Content Size Fitter and Anchors / UI Scaling? 2 Answers

[Unity 4.6 uGUI] Using uGUI and unity built in sprite packer does not reduce draw calls. 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges