Search Unity

Prevent key input when InputField has focus

Discussion in 'Input System' started by Huacanacha, Mar 26, 2019.

  1. Huacanacha

    Huacanacha

    Joined:
    Aug 16, 2013
    Posts:
    60
    Hi, what is the recommended way to block key input when an input field, or other part of the app that should "capture" keys, has focus? I don't want to disable the whole InputSystem, nor specific ActionMaps or Actions as they could be triggered by non-key input events.

    Another unrelated question: is there a way to specify multi-key actions? A use-case is could be pressing W to move forward at normal speed and shift+W to move forward quickly, or W+A to move on a diagonal where that differs from moving left+forward separately. Axis composites seem like they could address the W+A case but not general composite input.
     
  2. Huacanacha

    Huacanacha

    Joined:
    Aug 16, 2013
    Posts:
    60
    In the short term I am adding a line to each and every Action callback and exiting if an InputField currently has focus (via the EventSystem). This isn't ideal or scalable but works for now - plus I only have keys mapped to those actions so don't have to worry about also blocking non-key inputs yet.
     
  3. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    We're still missing some pieces here. Glad you're bringing it up. We're looking at options. But no question that for the most part, this should be pretty much automatic.

    As for what can be done ATM, silencing the keyboard altogether can be done by disabling it at the device level

    Code (CSharp):
    1. InputSystem.DisableDevice(Keyboard.current);
    2.  
    3. // And then later.
    4. InputSystem.EnableDevice(Keyboard.current);
    Not ATM. It's planned for >1.0 in the form of "chained bindings" (i.e. bindings that trigger only once all bindings in the chain have individually triggered).
     
    Energy0124 and Huacanacha like this.
  4. manpower13

    manpower13

    Joined:
    Dec 22, 2013
    Posts:
    140
    Hey there!

    Any update on this? I could not find any 'proper' way to tackle this issue. I'd say I'm missing something, since this is quite a trivial part of an input system.

    Selecting an inputfield (or any other selectable), and typing, always triggers all other actions related to those keys as well. I could not find any (preferably easy) way to disable this.

    Thank you!
     
    projectposeidon likes this.
  5. SteedMaker

    SteedMaker

    Joined:
    Dec 4, 2019
    Posts:
    5
    I am still seeing this issue - using the latest version 2019.3.15f1
     
  6. suryakumara33

    suryakumara33

    Joined:
    Nov 28, 2019
    Posts:
    3
    Any update for this ?
     
  7. phacee

    phacee

    Joined:
    Apr 5, 2020
    Posts:
    1
    I don't know if this is a good way to tackle this problem, but I am trying to handle it by creating a singleton input manager and reading in all my inputs there, and storing them as new values that I can reference throughout my project. That way I can block/disable any input I want by not setting the "new value" based on whatever information I want to block it on.

    In the code below the JournalNotes is the input field that I want to block my other keybinds when typing in.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using TMPro;
    5.  
    6. public class InputManager : MonoBehaviour
    7. {
    8.     public float HorizontalMovement;
    9.     public float VerticalMovement;
    10.     public bool Interact;
    11.     public bool Inventory;
    12.     public bool Journal;
    13.  
    14.     // An input field that I want to block other keybinds when typing in.
    15.     public TMP_InputField JournalNotes;
    16.  
    17.     #region Signleton
    18.  
    19.     public static InputManager Instance { get; private set; }
    20.  
    21.     // This makes sure that this object stays alive through scenes and that multiple aren't created.
    22.     private void Awake()
    23.     {
    24.         if (Instance == null)
    25.         {
    26.             Instance = this;
    27.             DontDestroyOnLoad(gameObject);
    28.         }
    29.         else
    30.         {
    31.             Destroy(gameObject);
    32.         }
    33.  
    34.     }
    35.     #endregion
    36.  
    37.     // Update is called once per frame
    38.     void Update()
    39.     {
    40.         HandleMovementInput();
    41.         HandleInteractInput();
    42.         HandleInventoryInput();
    43.         HandleJournalInput();
    44.     }
    45.  
    46.     private void HandleMovementInput()
    47.     {
    48.         // If the player is typing in their journal don't move them.
    49.         if (JournalNotes != null && !JournalNotes.isFocused)
    50.         {
    51.             HorizontalMovement = Input.GetAxisRaw("Horizontal");
    52.             VerticalMovement = Input.GetAxisRaw("Vertical");
    53.         }
    54.         else
    55.         {
    56.             HorizontalMovement = 0;
    57.             VerticalMovement = 0;
    58.         }
    59.     }
    60.  
    61.     private void HandleInteractInput()
    62.     {
    63.         // If the player is typing in the journal don't let them interact wtih other things.
    64.         Interact = JournalNotes != null && !JournalNotes.isFocused && Input.GetKeyDown(KeyCode.E);
    65.     }
    66.  
    67.     private void HandleInventoryInput()
    68.     {
    69.         // If the player is actively typing don't let them change to the inventory tab.
    70.         Inventory = JournalNotes != null && !JournalNotes.isFocused && Input.GetButtonDown("Inventory");
    71.     }
    72.     private void HandleJournalInput()
    73.     {
    74.         // If the player is activly typing don't let them open and close the journal.
    75.         Journal = JournalNotes != null && !JournalNotes.isFocused && Input.GetButtonDown("Journal");
    76.     }
    77.  
    78. }
    79.  
     
  8. kasuyakema

    kasuyakema

    Joined:
    Sep 13, 2020
    Posts:
    11
    I wrote an inputmanager that fires selection change events and disables input while an InputField has focus:
    (ExternalCoroutine is not needed if your InpuManager is a MonoBehaviour)
    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. using UnityEngine.Events;
    4. using UnityEngine.EventSystems;
    5. using UnityEngine.UI;
    6.  
    7. public class InputManager
    8. {
    9.     public static InputManager instance;
    10.     public static InputClass controls;
    11.     public UnityEvent<GameObject> OnSelectedChange = new FocusChangeEvent();
    12.     GameObject selected;
    13.     InputField selectedInputField;
    14.  
    15.     bool inputLocked = false;
    16.  
    17.     [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
    18.     private static void init()
    19.     {
    20.         new InputManager().Start();
    21.     }
    22.  
    23.     private void Start()
    24.     {
    25.         if (instance == null)
    26.         {
    27.             instance = this;
    28.         }
    29.         else
    30.         {
    31.             return;
    32.         }
    33.  
    34.         #region setup input
    35.         if (controls == null)
    36.         {
    37.             controls = new InputClass();
    38.         }
    39.         controls.UI.Enable();
    40.         #endregion
    41.  
    42.         ExternalCoroutine.instance.StartChildCoroutine(CheckFocus());
    43.     }
    44.  
    45.     private IEnumerator CheckFocus()
    46.     {
    47.         EventSystem eventSystem = EventSystem.current;
    48.         while (true)
    49.         {
    50.             if (selectedInputField != null)
    51.             {
    52.                 if (selectedInputField.isFocused)
    53.                 {
    54.                     if (!inputLocked)
    55.                     {
    56.                         inputLocked = true;
    57.                         controls.UI.Disable();
    58.                         controls.Player.Disable();
    59.                     }
    60.                 }
    61.                 else
    62.                 {
    63.                     if (inputLocked)
    64.                     {
    65.                         inputLocked = false;
    66.                         controls.UI.Enable();
    67.                     }
    68.                 }
    69.             }
    70.  
    71.             if (selected != eventSystem.currentSelectedGameObject)
    72.             {
    73.                 selected = eventSystem.currentSelectedGameObject;
    74.                 if (selected != null)
    75.                 {
    76.                     selectedInputField = selected.GetComponent<InputField>();
    77.                 }
    78.                 OnSelectedChange.Invoke(selected);
    79.             }
    80.  
    81.             yield return null;
    82.         }
    83.     }
    84.  
    85.     class FocusChangeEvent : UnityEvent<GameObject>
    86.     {
    87.  
    88.     }
    89. }
    90.  
     
    Energy0124 and Xtro like this.
  9. zdolezal

    zdolezal

    Joined:
    Sep 27, 2017
    Posts:
    75
    Sorry for necro but how's that being done now with TMP Text fields?
    Is there a best practice to ignore the actions when typing into the input field?

    I was just checking the current selected object whether it's the input field but that's pretty lame and you need to put it in every action handler.

    Input system verison: 1.1.1
     
  10. Xtro

    Xtro

    Joined:
    Apr 17, 2013
    Posts:
    608
    How can it be a necro since the problem is big and still current after this many years?
     
    zdolezal likes this.
  11. goldbug

    goldbug

    Joined:
    Oct 12, 2011
    Posts:
    767
    This makes input fields unusable. How is this still an issue 3 years later?
     
    Huacanacha likes this.
  12. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    Ah damn, thought I was missing something obvious but this is a real issue? Time to go make some hacky code :-(
     
    palourde likes this.
  13. YourWaifu

    YourWaifu

    Joined:
    Oct 4, 2015
    Posts:
    45
    Rene-Damm new input system was supposed to help programmers do without dirty code.
    But the problem described by the author of the post is still relevant
     
    cp- and Energy0124 like this.
  14. niuage

    niuage

    Joined:
    Nov 17, 2019
    Posts:
    122
    Any update on this?

    Is there a way for input fields in UI toolkit to stop the propagation of the events so that the input system doesnt pick them up?
     
  15. emredesu

    emredesu

    Joined:
    Aug 12, 2021
    Posts:
    55
    Still no proper solution without creating hacky code huh...
     
  16. Xtro

    Xtro

    Joined:
    Apr 17, 2013
    Posts:
    608
    At this point, we don't even know if there is any Unity team member working on this part of the engine after those massive layoffs. :(