Search Unity

How to get keyboard input for UI buttons

Discussion in 'Scripting' started by johnc81, Apr 19, 2021.

  1. johnc81

    johnc81

    Joined:
    Apr 24, 2019
    Posts:
    142
    Hello,

    I have a for loop which instantiates 4 button prefabs in a UI panel with a Layout Grid Group and Content Size Fitter component attached.

    The Player triggers the UI panel to become active when they walk over a certain area. The first button instantiated should be the one selected with the selected colour. What I need is to be able to control the UI using the keyboard arrow buttons and press space for the OnClick event.

    The problem is that when the Panel is active and the buttons have been generated, the arrow buttons still only control the Player in the background.

    How do I get the focus to be on the UI panel and stop the navigation on the Player?

    Here is the script for instantiating the buttons on the panel:
    Code (CSharp):
    1. private void PopulateUIPanel() {
    2.         UIController.instance.questionText.text = theQuestion;
    3.         for (int i = 0; i < answerList.Count; i++) {
    4.             GameObject newbutton = Instantiate(optionButton) as GameObject;
    5.             QuestionOptionButton button = newbutton.GetComponent<QuestionOptionButton>();
    6.             button.AnswerText.text = answerList[i].ToString();
    7.             button.TheAnswer = answerList[i];
    8.             if (answerList[i] == _equationAnswer) {
    9.                 button.IsAnswer = true;
    10.             } else {
    11.                 button.IsAnswer = false;
    12.             }
    13.             if (i == 0) {
    14.                 EventSystem eventSystem = button.gameObject.AddComponent(typeof(EventSystem)) as EventSystem;
    15.                 eventSystem.firstSelectedGameObject = button.gameObject;
    16.             }
    17.             newbutton.transform.SetParent(spacer, false);
    18.         }
    19.     }
    This code works perfectly when using the mouse, just need to know how to use keyboard input. I added the EventSystem component to the first button instantiated in the hope this would do something, but it didn't.

    Many Thanks,

    J
     
  2. Sphinks

    Sphinks

    Joined:
    Apr 6, 2019
    Posts:
    267
    I´m not sure if it stops the player from walking or if it has any other side effects, but maybe you could try something like this:

    Code (CSharp):
    1. GameObject yourUIPanel;
    2.  
    3. void Update()
    4. {
    5.     if (Input.GetKeyDown(KeyCode.DownArrow) && yourUIPanel.IsActive)
    6.     {
    7.         // Select next button
    8.     }
    9. }
    This has to be done in a script, which is attached to your player
     
  3. johnc81

    johnc81

    Joined:
    Apr 24, 2019
    Posts:
    142
    Hi,

    Thank you for your response. I actually tried something similar, by setting the Time.timeframe to zero so it would stop the player from moving.

    I am not sure how to set the focus to the UI Panel because even when it is stopped, the focus still seems to be on the Player.

    Many Thanks,

    J
     
  4. johnc81

    johnc81

    Joined:
    Apr 24, 2019
    Posts:
    142
    Hi,

    I think I am getting somewhere now. Not sure if this is the most efficient way of doing this, but it works at least:

    Code (CSharp):
    1.     private void PopulateUIPanel() {
    2.         UIController.instance.questionText.text = theQuestion;
    3.         for (int i = 0; i < answerList.Count; i++) {
    4.             GameObject newbutton = Instantiate(optionButton) as GameObject;
    5.             QuestionOptionButton button = newbutton.GetComponent<QuestionOptionButton>();
    6.             button.AnswerText.text = answerList[i].ToString();
    7.             button.TheAnswer = answerList[i];
    8.             if (answerList[i] == _equationAnswer) {
    9.                 button.IsAnswer = true;
    10.             } else {
    11.                 button.IsAnswer = false;
    12.             }
    13.             if (i == 0) {
    14.                 EventSystem eventSystem = GameObject.FindGameObjectWithTag("EventSystem").GetComponent<EventSystem>();
    15.                 eventSystem.firstSelectedGameObject = button.gameObject;
    16.                 eventSystem.SetSelectedGameObject(button.gameObject);
    17.                 eventSystem.sendNavigationEvents = true;
    18.             }
    19.             newbutton.transform.SetParent(spacer, false);
    20.         }
    21.     }
    I was previously adding an EventSystem component to the first button that was instantiated, but that doesn't seem to work. So instead, I added a tag to the EventSystem under the main Canvas, make reference to that and set some values. The one that seems to control whether I can use the keyboard to navigate is Send Navigation Events.

    I also set Time.timescale to zero for my player when the panel is active to stop my player from taking input.

    If there is a better or more performant way to do this, please let me know.

    Many Thanks,

    J