Search Issue Tracker
Fixed in 5.6.0
Votes
1
Found in
5.5.0f3
Issue ID
861736
Regression
Yes
UI Button doesn't update its SelectionState after interactable value change
To reproduce:
1. Open attached project "buttonstates.zip".
2. Play "Scene" scene.
3. Click on left button, then on the right. When Button becomes interactable again, it's state Color is not updated (it's green).
4. If you press "space" you can enable/disable Left Button.
5. Press Left button, so it's red and then press "space" to disable it. Now when you make it interactable it again, it will be red.
Expected result: When button.interactable is set to true, after it was false, button's Color is updated to the correct one.
Actual result: When button.interactable is set to true, after it was false, button's Color is not updated, stays the same as it was when "button.interactable" was set to false.
Reproduced with: 5.4.2p2, 5.5.0f3, 5.6.0b1
Not reproduced: 5.3.4p1, 5.4.2p1
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- Tile Palette selected dropdown text does not update when palette is renamed
- ArgumentException thrown and reference to Template gets unset when opening UXML file after editing referenced Template in Play mode
- [iOS][WebGL] Player freezes when multiple properties of a VisualElement are changed at the same time
- Warning 'GetControlID at event ValidateCommand returns a controlID different from the one in the Layout event' is logged when undoing the deletion of an Edited Freeform 2D Light
- ShadowCaster2D breaks on certain Rotation positions when Casting Source is set to PolygonCollider2D
KMQ_IGT
Apr 12, 2017 17:30
I am still seeing this in 5.6f3 on a set of simulated "tabs".
It seems pretty clearly a case of the transition to intractable = false does not clear the highlight state. I'm sure there are further issues if navigation is enabled.
Since I'm not using navigation my work around is to trick the button into thinking the pointer has left it before deactivating:
button.OnPointerExit(null);
button.interactable = false;
I've been having to do a lot of interesting hijacking of the input model like this lately for other interactions like getting scroll lists to work inside of each other.
Artifact-Jesse
Feb 02, 2017 20:46
Please, please fix this in 5.5
hadesfury
Feb 02, 2017 13:24
it's happening in 5.5.1p1
hadesfury
Jan 12, 2017 12:59
Is it planned to fix it in 5.5 at least cause it's a really annoying bug
danijmn
Dec 19, 2016 17:35
Had a look at the 5.4.2 UI source with ILSpy and compared it to the 5.4.3 source. I believe this regression is a result of a poor attempt to fix issue 826310.
There is exactly one different line of code in Selectable.cs, in the function "EvaluateAndTransitionToSelectionState(BaseEventData eventData)".
The line in question used to to be (as of 5.4.2): if (!this.IsActive()) ... return
Now it is (as of 5.4.3): if (!this.IsActive() || !this.IsInteractable()) ... return
So the rest of the function isn't processed when the selectable is considered not interactable.
To be more specific, the function is called by OnDeselect, OnSelect, OnPointerEnter, OnPointerExit, OnPointerUp and OnPointerDown...which means that state changes are completely ignored when the selectable (or its canvas group) is marked as not interactable.
This breaks a lot of important stuff including setting the button as selected/deselected from script, and also causes some visual issues like highlighted buttons not going back to normal state if the canvas group is disabled and reenabled.
One can temporarily solve the problem by making a new script deriving from Button, overriding all those functions, as well as IsInteractable. As an example:
public override void OnDeselect(BaseEventData eventData){
forceInteractable = true;
base.OnDeselect(eventData);
forceInteractable = false;
}
(Remember to make IsInteractable check the "forceInteractable" field before calling its base implementation)
Merry Christmas!
P.S.: the UI repository is outdated, which is why I had to use ILSpy to begin with