Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Is it possible to create a UI where only one object can be highlighted at a time?

Discussion in 'UGUI & TextMesh Pro' started by steinbitglis, Oct 15, 2015.

  1. steinbitglis

    steinbitglis

    Joined:
    Sep 22, 2011
    Posts:
    251
    I'm trying to create what I consider to be a standard menu for my game.

    The problems start when I use both the keyboard and a mouse. When hovering over any selectable, it is put into a highlighted state. This does not mean that it is the selected object, but it looks exactly the same (for standard buttons etc.), since selectable only knows that it's highlighted.

    Having multiple highlighted objects looks confusing, especially when using a gamepad.

    I know it's a small problem, but it's not trivial to work around, as far as I can see.

    [Edit:]
    I posted the same question on Answers
     
    Last edited: Oct 15, 2015
  2. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,683
    I think the case where multiple items can become highlighted is a known bug. In reality only 1 UI element can/should be highlighted at a time (unless you are using multi-touch).

    But because the "set state" functions are internal / private, we cannot change the state easily (as far as I know, unless someone has found a magic bullet)
     
  3. steinbitglis

    steinbitglis

    Joined:
    Sep 22, 2011
    Posts:
    251
    I have looked through the source code, and found explicit code that lets the 'Selectable' stay highlighted if the mouse cursor is still inside it, even if the selectable is deselected. I don't get why, and changing it means overriding a substantial amount of classes.

    The reason I'm asking anyway is that this feels like the most common use case to me.
     
  4. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,683
    The repeatable case is if you click the button/selectable, then it stays highlighted until another selectable is clicked.
     
  5. steinbitglis

    steinbitglis

    Joined:
    Sep 22, 2011
    Posts:
    251
    Also any navigation by keys/buttons in combination with hovering the mouse.
     
  6. theembracedone

    theembracedone

    Joined:
    Jul 31, 2019
    Posts:
    22
    Sorry for the massive necro... I've been trying to find a good way to work around this problem, have you figured it out since?
     
  7. steinbitglis

    steinbitglis

    Joined:
    Sep 22, 2011
    Posts:
    251
    Nope, we're still overriding a lot of classes, so that 'mouse hover' can be a thing.
     
  8. theembracedone

    theembracedone

    Joined:
    Jul 31, 2019
    Posts:
    22
    I found a solution for my own use case which is:
    I'd like users to have the ability to switch between using mouse, keyboard and gamepad controls, and in turn, seamlessly switch between navigating via mouse cursor and directional (WASD/Dpad).

    - when switching from cursor to directional, if nothing was selected, I want the first button on the screen selected*
    - when switching from cursor to directional, if something was selected, I want navigation to continue from there (ie if you have the 3th button selected, I want to select button 2 if I pressed UP)
    - when switching from directional to cursor, just lose all selection because chances are your mouse is not already hovered on anything anyway

    *I have a script that sets which button is this "first to be selected" button on every screen.

    As for the solution for anyone else who might stumble upon this issue:
    I'm using Rewired and when switching inputs, I fire an event that sets the width and height of the mouse's "movement area" to 0:

    Unity_4gGlif9eYx.png

    Unity_bGfjN85mYb.gif
    in this last GIF, you're seeing me changing my input between mouse and keyboard input and how switching to directional input changes movement area height/width to 0

    Doing only this does not remove the highlight the mouse hover leaves however, most probably because changing this movement area likely "teleports" the cursor instead of moving it, so it does not trigger pointerexit on the button, but you can overcome this by having a script on every selectable that essentially just triggers the selected button state on mouse over (note that I am using a UI manager so the below code might not be perfect for your needs, I have not tested it but this is in essence the core of it):

    Code (CSharp):
    1. public class ForceSelectedState: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
    2.     public UnityEngine.UI.Button button;
    3.  
    4.     public void OnPointerEnter(PointerEventData eventData) {
    5.         button.OnSelect(eventData);
    6.     }
    7.  
    8.     public void OnPointerExit(PointerEventData eventData) {
    9.         button.OnDeselect(eventData);
    10.     }
    11. }
    Then you have to make sure this script is on all the Selectables everywhere.

    In both of the following GIFs, I am mousing over a button then pressing arrow keys up/down before moving the mouse again:

    Default behaviour:
    Unity_SUQA0sXHWb.gif


    New behaviour:
    Unity_wSu1hDao6O.gif

    Im not sure how you'd clamp mouse movement area without Rewired, I know you can't move the mouse via code because it's handled by the OS and its a readonly value, but I'm sure there is some way without Rewired as well.

    Hope that helps someone
     
    ObsidianSpire likes this.