Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Feature request: option to disable deselect in UI Input Module

Discussion in 'Input System' started by seffles, Oct 15, 2019.

  1. seffles

    seffles

    Joined:
    Oct 2, 2013
    Posts:
    32
    I'd like to request that the UI Input Module be given an option to disable one of it's features: clicking an area of the screen with no selectable controls, the current selected game object is deselected.

    In my game, I expect the user to swap between mouse, keyboard and gamepad in the menus. If they deselect a button by clicking the background, all controls are deselected and navigation is either broken or not intuitive when they press the gamepad dpad or a cursor key. It presents a more professional feel if the current selected button stays selected and navigation continues to work seamlessly.

    For years I've been disabling this feature by modifying the source code of the Standalone Input Module to create my own version. Now the new input system is reaching maturity and I've started to use the UI Input Module component, I'm having to modify that too.

    It's a simple change. In InputSystemUIInputModule.cs, I comment out these two lines:
    Code (CSharp):
    1. // If we have clicked something new, deselect the old thing
    2. // and leave 'selection handling' up to the press event.
    3. //if (selectHandlerGO != eventSystem.currentSelectedGameObject)
    4. //    eventSystem.SetSelectedGameObject(null, eventData);
    If a checkbox were added to the inspector, the if statement would simply need to check that property as well as the existing condition.

    I hope you'll seriously consider this request. Thanks for listening.
     
    personalrt, Lisasz, tantix and 8 others like this.
  2. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    Just chiming in for visibility that I was curious about this too. Our (PC) game has local multiplayer via either MKB or Gamepad, so there's no real reason to favor one input method over the other, so would definitely appreciate having something like this.
     
    tommyvisic and seffles like this.
  3. Jichaels

    Jichaels

    Joined:
    Dec 27, 2018
    Posts:
    237
    Agreed, I've the exact same setup, and if you unselect accidently by clicking somewhere, there is no way to get something selected with keyboard or gamepad (except doing hacky stuff via code).

    Please add this !
     
    tommyvisic and seffles like this.
  4. nkennington

    nkennington

    Joined:
    Dec 17, 2018
    Posts:
    1
    Agreed. My current VR project uses local multiplay and different players using twin joysticks, mouse and keyboard in combination and we've encountered this issue.
     
    tommyvisic and seffles like this.
  5. Ofx360

    Ofx360

    Joined:
    Apr 30, 2013
    Posts:
    155
    Yes, please

    I actually keep the UI Input Module disabled because of this annoying quirk, and just trigger the button highlighting manually
     
    tommyvisic and seffles like this.
  6. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Posting just to let you know we're not ignoring this. Good feedback.
     
    tommyvisic, Iron-Warrior and seffles like this.
  7. seffles

    seffles

    Joined:
    Oct 2, 2013
    Posts:
    32
    Thanks, Rene. Great to hear, keep up the good work!
     
    tommyvisic likes this.
  8. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Tentative PR.

    One thing that struck me looking into this is that it seems wrong that navigation can be broken by the selection getting dropped. If there's no current selection, it seems that navigation should simply resume from the last object that *was* selected. Unfortunately, doesn't seem like there's a simple way to make that happen in the current uGUI event system setup.
     
    Alic, ASymShade, BossClaw and 3 others like this.
  9. seffles

    seffles

    Joined:
    Oct 2, 2013
    Posts:
    32
    Thanks for the update @Rene-Damm, very much appreciated.

    You're right about being able to resume, but I'm not sure which object you're suggesting should be selected. To clarify, I think it should re-select the last object that was selected, and IGNORE the navigation. E.g. if the user presses right, the object that was last selected becomes selected, not the one to the right of it.

    Hopefully you can find a suitable solution to the event system, but that's already good progress, thank you.
     
    tommyvisic likes this.
  10. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    Thanks for keeping us in the loop! Yeah, it does seem wonky that it's possible to end any navigation with deselecting. I can't really think of a use case for that. I'd imagine if you're using mouse for controls, navigation wouldn't be enabled, and if you were using mouse/gamepad, navigation would be enabled, and you'd rather it not get broken.
     
    tommyvisic likes this.
  11. Leonar3Do

    Leonar3Do

    Joined:
    Apr 20, 2015
    Posts:
    2
    This feature would be great for us. Before Unity 2019 we implemented our own InputSystem to create a virtual reality keyboard using UI and Buttons. We could disable deselecting when a keyboard button was pressed, so we could type in the input field by emulating system keyboard events. This is currently not possible: the XRUIInputModule does not provide virtual methods to override default behaviour (like StandaloneInputModule.ProcessMousePress) so whenever we press a VR keyboard button the input field loses focus.
     
    tommyvisic likes this.
  12. ABChief

    ABChief

    Joined:
    Apr 13, 2017
    Posts:
    1
    Ofx360, tommyvisic and seffles like this.
  13. Mathius123

    Mathius123

    Joined:
    May 21, 2018
    Posts:
    14
    Having encountered this issue myself, I explored the EventSystem.cs file using Unity 2019.3.12f1 and found in the method SetSelectedGameObject on line 150 (could be a different line number depending on the Unity version) that if I put this line of code at the very beginning of the method, it made it so you could never set the Selected gameObject to null:

    Code (CSharp):
    1. if (selected == null) return;
    It worked for me at this point in my project and I will post a follow-up if I run into any issues with it. Am I missing a very glaring issue this will cause outside of UI work?
     
    ilyamep likes this.
  14. ASymShade

    ASymShade

    Joined:
    May 18, 2018
    Posts:
    6
    Thank-you for implementing this. However, it feels as if the deselection is too aggressive, even with DeselectOnBackgroundClick off.

    One example would be Selectables that have their Navigation Mode set to None (i.e. Selectables that cannot actually become selected, and are used rather to implement a Transition or for other reasons). For applications that can be controlled using both a mouse and a gamepad, clicking the mouse cursor over such a Selectable will still trigger ProcessPointerButton's deselection of the currently selected GameObject, even though its expected 'replacement' does not seek to be selected, resulting in gamepad navigation breaking until something else is selected by other means.

    It is possible to workaround this, albeit not very cleanly, by locally altering the ProcessPointerButton condition to something like this:-

    Code (CSharp):
    1.                 // If we have clicked something new, deselect the old thing and leave 'selection handling' up
    2.                 // to the press event (except if there's none and we're told to not deselect in that case).
    3.                 if (selectHandler != eventSystem.currentSelectedGameObject && ( (selectHandler != null && ( null != selectHandler.GetComponent<UnityEngine.UI.Selectable>() ) && ( UnityEngine.UI.Navigation.Mode.None != selectHandler.GetComponent<UnityEngine.UI.Selectable>().navigation.mode ) ) || m_DeselectOnBackgroundClick))
    4.                     eventSystem.SetSelectedGameObject(null, eventData);
    But is there a better way of avoiding this situation?

    I'm sure there are some projects in which this would work, but in other cases you might actually want to be able to enter a state in which nothing is selected, even if only in rare circumstances.
     
    bluescrn likes this.
  15. MousePods

    MousePods

    Joined:
    Jul 19, 2012
    Posts:
    808
    @Rene-Damm

    I was wondering if this is coming for UIToolkit event system? I am having the same issues. I need, no matter what, to never deselect the focused VisualElement. It looks really bad when I touch the screen then try to use the gamepad I have to use two inputs before it moves correctly.

    Thanks!
     
  16. MousePods

    MousePods

    Joined:
    Jul 19, 2012
    Posts:
    808
  17. RichardJanssen

    RichardJanssen

    Joined:
    Apr 21, 2017
    Posts:
    14
    Along with some other things I had the same question. It's been answered in this post by uBenoitA: https://forum.unity.com/threads/gamepad-supported-ui.804534/#post-7037653.
     
    MousePods likes this.
  18. UrbanNuke

    UrbanNuke

    Joined:
    Jun 11, 2019
    Posts:
    21
  19. davidtabernerom

    davidtabernerom

    Joined:
    Jul 13, 2020
    Posts:
    2
  20. strictfp

    strictfp

    Joined:
    Jul 29, 2020
    Posts:
    13
    alex_roboto likes this.
  21. seffles

    seffles

    Joined:
    Oct 2, 2013
    Posts:
    32
    IIRC "Deselect On Background Click" doesn't work correctly if you click on a disabled control. The input module tries to select the disabled control and realises it can't, so sets the current selection to null. The background check ONLY checks for cases where the mouse click isn't over a control, so it's not a suitable fix.

    I'm grateful to Unity for adding this feature after I requested it, but it shouldn't have been necessary in the first place, the wait for implementation was too long, and the resulting feature was inadequate. I worked around the issue by building my own UI system on top of canvases and the UI interfaces (e.g. IPointerEnterHandler) instead.

    I figured Selectable was the root of the problem, so made an alternative out of small independent modules that let me mix and match functionality such as selectable, clickable, navigable, etc. It works incredibly well, allowing smooth switching between input devices (gamepad, mouse, touch, etc) and finer control over things. No more workarounds for issues like this, and adds a few missing features such as being able to show keyboard/gamepad focus and mouse hover state separately (something that always bothered me about uGui).

    Was it a lot of work? Yes. Was it worth it? Absolutely. We shipped one incredibly successful title with it on PC, Mac and Switch where it suports mouse, keyboard, gamepad and touch. It also works great on mobile and tablets, although we haven't shipped those. I built it as a package, so it's completely reusable and we're already using it in our next game.

    I say this not to blow my own trumpet, but to highlight that Unity really needs to eat its own dog food. We all know it but cancelling Gigaya was a mistake.
     
    WilsonCWong, bluescrn, Sarai and 2 others like this.
  22. webik150

    webik150

    Joined:
    Mar 23, 2013
    Posts:
    62
    Deselect on background also doesn't prevent the user to deselect the UI by right-clicking, which is something I would love to prevent.
     
    Kitamat likes this.
  23. Sarai

    Sarai

    Joined:
    Jul 20, 2014
    Posts:
    30
    bump
     
    Kitamat likes this.
  24. bluescrn

    bluescrn

    Joined:
    Feb 25, 2013
    Posts:
    642
    I'm trying to deal with mouse vs controller woes by implementing a custom Selectable that only shows/updates the selection when using controller/keyboard, and only shows the highlight when using mouse - so if using mouse, there's still a valid keyboard/controller selection, just hidden.

    It mostly works, but the aggressive/unnecessary deselection is getting in the way of this, and it looks like the only real workaround is editing the UI package itself :(
     
  25. WilsonCWong

    WilsonCWong

    Joined:
    Mar 20, 2013
    Posts:
    35
    Unbelievable this is still a thing almost 5 years later. If any of you are interested in fixing the deselection upon clicking disabled controls (interactable set to false) and upon clicking a control with any of the other mouse buttons, I modified InputSystemUIInputModule.cs with the following at around Line 471 and it seems to do the trick:

    Code (CSharp):
    1.  
    2. var selectHandler = ExecuteEvents.GetEventHandler<ISelectHandler>(currentOverGo);
    3. var selectable = currentOverGo != null ? currentOverGo.GetComponent<Selectable>() : null;
    4. var isInteractable = selectable != null ? selectable.interactable : false;
    5.  
    6. // If we have clicked something new, deselect the old thing and leave 'selection handling' up
    7. // to the press event (except if there's none and we're told to not deselect in that case).
    8. if (selectHandler != eventSystem.currentSelectedGameObject && (selectHandler != null || m_DeselectOnBackgroundClick)) {
    9.     if (m_DeselectOnBackgroundClick)
    10.         eventSystem.SetSelectedGameObject(null, eventData);
    11.     else if (selectHandler != null && isInteractable && eventData.button == PointerEventData.InputButton.Left) {
    12.         eventSystem.SetSelectedGameObject(null, eventData);
    13.     }
    14. }
    15.  
    You'll have to embed the input system package into your project to do this, which you'll likely have to do anyways like I had to for 1.7.0 to apply a bug fix manually since they don't want to backport it to a STABLE release for some reason...I'll stop ranting.
     
    Last edited: Mar 15, 2024