Unity 4.6 UI button highlight color staying after button clicked

I have a standard UI Button within a panel, and a different color for each of the transition states, to make it easy to identify which state it is in. Each state works as intended, except after I click on a button, the state transitions from the ‘Pressed Color’ back to the ‘Highlighted Color’.

Unfortunately, it persists in this state even after moving the mouse off of the button. Clicking anywhere else within game sets the button back to the ‘Normal Color’ state.

I have adjusted different properties, but there really aren’t that many related properties on a button that would affect this, so I am having trouble with it.

Got the problem too, it’s due to the navigation system for keyboard only usage. put navigation on none on your button script and it will work :wink:

Rather than disabling navigation you can do this.

All you need to do is remove the currently selected object from the event system, since technically, the button is then the ‘selected’ object after clicking it. Its like the windows ‘focus’ rect around the current field.

using UnityEngine.EventSystems;

EventSystem.current.SetSelectedGameObject(null);

If you pop that into your buttonpressed script/method, then it will remove the selection and colour immediately.

In my case, setting the navigation to NONE didn’t work.
The solution is to disable and re enable the button component and if you have animations, trigger the “Normal” animation transition.

GetComponent<Button> ().enabled = false;
GetComponent<Button> ().enabled = true;
GetComponent<Animator> ().SetTrigger("Normal");

Wouldn’t this be solved if they include a Hover state?

This will give you full control, you could make the state different from the Highlight state and users do not get confused with two highlighted elements and you can still keep using the keyboard/joystick navigation system.

In this case you could also have the choice to decide whether the button should be different in a hover state or stay the same if you do not want that behavior! :slight_smile:

I think most importantly it should work correctly for one input at a time. The navigation features are especially important for those with disabilities using alternate controls (via keyboard interface typically). So making a custom user experience that involves a combo of mouse and keyboard at the same time seems counter-productive to me. This is exactly why I cringe whenever someone suggests the “fix” is to turn navigation off entirely.

Right now though, the way the navigation and hover uses the same highlight just causes confusion in most cases.

For your original suggestion, it could be achieved using an Event Trigger with PointerEnter and PointerExit and apply a temporary overrideSprite as a “hover”.

(This answer was written as of Unity 2017.3.1.)

I’ve got an answer that is even simpler and more direct than EventSystem.current.SetSelectedGameObject(null) that worked for me.

using UnityEngine;
using UnityEngine.EventSystems;

public class DemoPointerOffClass : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
    private Button _btn;

    private void Awake()
    {
        _btn = this.gameObject.GetComponent<Button>();
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        _btn.OnSelect(eventData);
    }

    public void OnPointerExit(PointerEventData eventData)
   {
        _btn.OnDeselect(eventData);
   }
}

Put this script on the same object that you have your button on. I do NOT understand why the Button component does not called Button.OnDeselect by default when a pointer exits its hitbox, but alas.

So, I was having a similar issue, but I was able to solve it without turning off navigation as I wanted the UI to work both with Controllers/Keyboard (buttons) and Mouse Pointer.

First, I suggest using this, as my code uses it, though I wouldn’t be surprised if there was a way around using this PointerEventData.
http://forum.unity3d.com/threads/global-pointer-events.283895/

Anyways, the way I solved this is to do a SendMessage(“OnPointerExit”, PointerEventData) when I detect if someone has pressed a keyboard button or moved the analog stick/dpad.

Hopefully this answer will help someone out.

Simple Code Example:

private void OnGUI()
        {
            //this gives us constant information on what is happening
            mouseData = EventSystem.current.GetComponent<StandaloneInputModuleCustom>().GetLastPointerEventDataPublic(-1);

            string verticalAxisName = EventSystem.current.GetComponent<StandaloneInputModuleCustom>().verticalAxis;

            if (mouseData.IsPointerMoving())
            {
                if(mouseData.pointerEnter != null)
                    EventSystem.current.SetSelectedGameObject(mouseData.pointerEnter);
            }

            //check to see if input has been pressed that isn't the mouse and turn off mouse logic
            if (Input.GetAxis(verticalAxisName) != 0 || Input.GetButtonDown(verticalAxisName))
            {
                mouseData.selectedObject.SendMessage("OnPointerExit", mouseData);
            }
        }

@justin35f

myCanvas.transform.FindChild(“something”).GetComponent().color = myCanvas.transform.FindChild(“something”).GetComponent().colors.pressedColor;

I believe you can understand the rest, such as initiating which buttons to be pressed at startup, checking if pressed using if(), and then setting it to be pressed after user had clicked the button.

Good luck

For anyone who wants both keyboard and mouse selection to work, you will need to use IPointerEnterHandler,IPointerExitHandler,IDeselect Handlers.

You can make a script with this function and attach it to the buttons in your game to get them to both work correctly.

public void OnDeselect(BaseEventData data)
{
	selectable.enabled = false;
	selectable.enabled = true;
}

public void OnPointerEnter (PointerEventData eventData)
{
	if (!EventSystem.current.alreadySelecting) {
		EventSystem.current.SetSelectedGameObject (gameObject);
	}
}

public void OnPointerExit (PointerEventData eventData)
{
	selectable.OnPointerExit (null);
}

If you want to use navigation and also remove this problem use this solution:

void Update()
    {
        if (Input.GetMouseButtonUp(0))
        {
            EventSystem.current.SetSelectedGameObject(null);
        }
    }

Unity 2018… bug still exists. My solution, add the following script to each button.

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;// Required when using Event data.


/// <summary>
/// This script addresses the Unity bug that buttons stay highlighted after you select them
/// and then move off the button.
/// This results in two buttons being active at the same time.
/// https://forum.unity.com/threads/clicking-a-button-leaves-it-in-mouseover-state.285167/
/// https://answers.unity.com/questions/854724/unity-46-ui-button-highlight-color-staying-after-b.html
/// https://docs.unity3d.com/ScriptReference/UI.Selectable.OnPointerExit.html
/// My solution was based off a couple of answers together.
/// </summary>



public class ARButtonHighlightfix : MonoBehaviour, IPointerExitHandler// required interface when using the OnPointerExit method. {
{
    //Do this when the cursor exits the rect area of this selectable UI object.
    public void OnPointerExit(PointerEventData eventData)
    {
        //Debug.Log("The cursor exited the selectable UI element.");
        EventSystem.current.SetSelectedGameObject(null);
    }
}

Unity 2017.3.1f1 - same problem here.

If you don’t need controller support, setting navigation to “None” is fine UNLESS you instantiate buttons (use a prefab) and set up an “onClick” (“myButton.onClick.AddListener(ClickMethod)”) for them at runtime because then “EventSystem.current.currentSelectedGameObject.GetComponent()” just throws an exception!

In this case bilalseh’s solution works perfectly:
Just add
EventSystem.current.SetSelectedGameObject(null);

directly AFTER getting the currently selected button from the event system. Since it’s in an “onClick” method, you don’t even have to use “Update()” and also also don’t need “Input.GetMouseButtonUp(0)”;

Unfortunately there’s a big BUT: No matter what the navigation is set to, as soon as you use a touchscreen, the buttons don’t properly reset, even if you reset the EventSystem by hand. :confused: Still trying to get that fixed, so if anyone has a suggestion for that I would be grateful!