[Button] Keyboard and Mouse Highlighting

Hi.
I’m working on a code generated menu that should work with both keyboard and mouse inputs.

  1. I call EventSystem.current.SetSelectedGameObject(firstMenuOption) to get the first button highlighted
  2. If the user decides to use the mouse instead of the keyboard
  3. Then both the firstMenuOption and the button under the mouse cursor is in the highlighted state

I assume this is expected behaviour? Should I run through all my buttons and deselect them if the mouse is over a button ? Or is there some other built in way of handling button highlighting with both the keyboard and mouse ?

An example of this can be seen from example 5 onwards: http://reyn.vlietstra.co.za/?page_id=248

Thanks!

??
By having both the StandaloneInputModule and the TouchInputModule attached to the EventSystem in your scene (the default),you should have both mouse / keyboard and touch input for your UI, without doing anything else.

Or is there something I’m missing in your query?

Hi Simon.
Both the mouse and keyboard input is working.

I would like only one of my menu buttons to be highlighted at any one time.

At the moment the button that is explicitly selected with SetSelectedGameObject is always highlighted, in addition to whatever button the mouse cursor is over.

Could it be that both the input module components are separately keeping their own selected item causing two buttons to be highlighted in my UI ?

Please check Example 5/6/7/8 in the supplied link.

Thanks!

I’ll check out your example tonight.

The EventSystem is the central manager that maintains what is selected / clicked and which input system is being assessed.
It could be this is an actual bug with the SetSelectedGameObject function where is causes the set object to remain set regardless of the next update.

Hello!

I’m having some kind of trouble with that too. I created a function that is triggered when your mouse cursor pass over a button:

public void SetTheButtonMouseIsOver (GameObject currentButton)
{
EventSystem.current.SetSelectedGameObject(currentButton, null);
}

Now, when I’m using the keyboard and decide to use the mouse, I don’t get 2 highlighted buttons anymore, only the one under the cursor.

But…
If a button is highlighted because of the cursor that is over it, when I decide to use the keyboard, even if I press any arrow and select another option, the button under the cursor is still highlighted. Tried to creat a boolean, but it didn’t work:

//MOUSE
public float currentMouseX;
public float currentMouseY;
public bool usingKeyboard;

void Update ()
{
if(GameObject.Find(“Main Camera”).GetComponent().pauseOn)
{
if(Input.GetAxis(“Mouse X”) != currentMouseX || Input.GetAxis(“Mouse Y”) != currentMouseY)
{
usingKeyboard = false;
currentMouseX = Input.GetAxis(“Mouse X”);
currentMouseY = Input.GetAxis(“Mouse Y”);
}
}
}

public void SetTheButtonMouseIsOver (GameObject currentButton)
{
if(!usingKeyboard)
{
EventSystem.current.SetSelectedGameObject(currentButton, null);
}
}

//This one is called when I move using keyboard
public void UpdateCurrentButton (GameObject currentButton)
{
usingKeyboard = true;
}

Already tried to make the canvas unblock the raycast and other stuff, but nothing worked…
I was thinking about changing the animation state of the button under the cursor via script (could do this inside this last function, instead of just turning the bool on), but I don’t know how to do that lol

It has been noted there is a bug with the highlighting code at the moment, it doesn’t clear the highlighted state of the previous control sometimes.
You can test this by adding two buttons, highlight one, click on it and then move the pointer over another. The result is two buttons in a highlighted state. UT are aware of the issue at the mo as far as I know.

1 Like

Same Issue Here, have you fixed?

Bump. Have the same issue. Was this fixed?

I still have the issue. Very disappointing.

After some digging around in the Unity UI source on BitBucket I came up with the following solution. The problem seems to be that the Selectable component (on which Button is based) uses the “highlight” state for two different cases (selected and hovering) and doesn’t clearly distinguish between the two. This causes a deselected object to remain highlighted because OnPointerExit hasn’t been called. My solution is to automatically select the object on pointer enter (which might have repercussions but works for my needs) and automatically trigger the OnPointerExit behavior when deselected.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;


[RequireComponent(typeof(Selectable))]
public class HighlightFix : MonoBehaviour, IPointerEnterHandler, IDeselectHandler
{
    public void OnPointerEnter(PointerEventData eventData)
    {
        if (!EventSystem.current.alreadySelecting)
            EventSystem.current.SetSelectedGameObject(this.gameObject);
    }

    public void OnDeselect(BaseEventData eventData)
    {
        this.GetComponent<Selectable>().OnPointerExit(null);
    }
}
12 Likes

Thanks - that works just fine for my purposes, too. I’m usuing Unity 5.6 and it seems to still be an issue.

For anybody reading, the only thing the quoted post might not make clear is that this script should be attached to any buttons you want to properly reselect if/when the user switches from a keyboard to mouse input.

2 Likes

2022 checking in. I’m up against the “mouse cursor still highlighting buttons” problem. This script solved the issue, but, introduced a new problem which is a button with the script will remain highlighted when the mouse cursor leaves it.

In this GIF the quit button doesn’t have the script. The others do.

I made a change to the script so that the selection gets lost (i.e. no active selected object) when the mouse cursor leaves. It works for me now but I am not sure about the edge case.

    [RequireComponent(typeof(Selectable))]
    public class HighlightFix : MonoBehaviour, IPointerEnterHandler, IDeselectHandler, IPointerExitHandler
    {
        public void OnPointerEnter(PointerEventData eventData)
        {
            if (!EventSystem.current.alreadySelecting)
                EventSystem.current.SetSelectedGameObject(this.gameObject);
        }

        public void OnPointerExit(PointerEventData eventData)
        {
            if (EventSystem.current.currentSelectedGameObject == this.gameObject)
                if (!EventSystem.current.alreadySelecting)
                    EventSystem.current.SetSelectedGameObject(null);
        }

        public void OnDeselect(BaseEventData eventData)
        {
            this.GetComponent<Selectable>().OnPointerExit(null);
        }
    }
4 Likes