Unity study notes detailed explanation of the selection state of the Ugui Button button and alternative solutions

foreword

The opportunity to write this article is to realize the visual feedback of different states of a button interaction. After an in-depth understanding of the native selection state of the Button, I found that there is a hidden mystery here , which is worth leaving a note.

Button state property introduction

As you can see in the Inspector panel, Unity provides five states for the button, which are:

  • Normal : Normal state, i.e. found nothing
  • Highlighted : Highlighted state, that is, after the pointer enters the button, there is no other operation such as pressing
  • Pressed : Pressed state, that is, the pointer is pressed in the button
  • Disabled : Disabled state, corresponding to the parameter Interactable (whether interactive)

And in Transition, you can choose the representation of the state, which are

  • Color Tint : Color transition
  • Sprite Swap : Image transition
  • Animation : animated transitions

The mystery

Who decides the change of the selection state of the button? Here we will enter the underlying code of Unity to view.

The judgment and implementation logic responsible for the selection state are completed in the “Selectable.cs” script, which has a parameter named ” currentSelectionState“, which is the protagonist of this article. It can be clearly seen here that different events triggered by the pointer correspond to currentSelectionStatedifferent states.

With the above understanding, go back to the presentation layer of the button to take a closer look at the so-called ” hidden mystery “.

For the convenience of explanation, I made a visual display of the state of the button (there is an online experience connection later).
Through the different interactions of the buttons can be found:

  • The button defaults to the Normal state at the beginning. When the pointer enters the button (OnPointerEnter), the Highlighted state will be triggered immediately. If there is no pressing action at this time, leave the button (OnPointerExit), it will return to the Normal state
  • Secondly, if the pointer enters the button and performs the action of pressing (OnPointerDown) and does not release the pointer (OnPointerUp) within this time period, the button is in the Pressed state.
  • Then, after pressing and releasing the pointer, the button will go from the Pressed state to the Selected state.
  • At this point, if the pointer leaves the button, or re-enters the button after leaving, the button will always be in the Selected state.
  • The Selected state will be canceled only when the pointer performs the pressed action. That is to say, when the button is Selected, the button can only exit the Selected state by pressing other places.
  • Finally, the Disable state is only determined by the switch value of Interactable

The “interesting” part here is the Selected state. I don’t know the specific reason for Unity’s design, but it can be understood that after the button is pressed, the Selected state is actually equivalent to a “lock (lock)” state. The button returns to its normal state.

From a design point of view, this visual feedback is actually in conflict with the interactive state. People who are not familiar with the underlying principles will not be so concerned. I have a button, and there are only several states during interaction. I don’t need to care whether the button is locked or not. All I want is to move the mouse into the button, and the button is displayed in the Highlighted state. This is no problem, and then when the button is clicked, the button It is displayed in the Pressed state, which is no problem, but after releasing it, what the hell is this locked state, my mouse is in the button, it should return to the highlighted state, even if I remove the button, it also returns Don’t go to Normal state, what kind of thing is this unity!

That is to say, the interaction state switching is obviously very simple, but it does not meet the implementation requirements on the original Button.

Alternative – Alternative Button

I don’t know if someone will write a set of special logic for this effect, listen to different events of Pointer through TriggerEvent and then change the color or texture of the button. It is not impossible to do this, but if there are more buttons, it will be very difficult. Difficult to maintain and not a desirable solution.

In order to achieve the correct effect, and to do it in a way with minimal overhead, try the following methods.

The first thing to be sure is that my button is only used for “button” function, and does not need the so-called “Selected” judgment.

Implementation principle:

Because it currentSelectionStateis not an external parameter, there is no way to achieve the effect by directly modifying this state value.

Only through the interface function provided by “Selectable.cs” – DoStateTransition(), the function of this function is to perform the corresponding animation transition effect when the state changes, that is, the color change we just saw.

/// <summary>
/// Transition the Selectable to the entered state.
/// </summary>
/// <param >State to transition to</param>
/// <param >Should the transition occur instantly.</param>
protected virtual void DoStateTransition(SelectionState state, bool instant)
{
    .....
}

With this interface, it is easy to handle, and the Button script can be extended.

First of all, it can be clearly understood that there are three places for the state transition that the Button lacks:

  • state1: After clicking the button, if the button is not left, it should switch to the Highlighted state
  • state2: After clicking the button, the moment you leave the button, it should switch to Normal state
  • state3: After clicking the button, leave the button and return to the button, it should switch to the Highlighted state

Then, the animation that changes the state is executed in the corresponding pointer event.

The addition of state1 is done in the OnClicked event

onClick.AddListener(() => {DoStateTransition(SelectionState.Highlighted, false); });

The addition of state2 is done in OnPointerExit

DoStateTransition(SelectionState.Normal, true);

The addition of state3 is done in OnPointerEnter

DoStateTransition(SelectionState.Highlighted, true);

The complete code is as follows. To achieve the effect, directly replace the script with the Button script of the button to achieve the effect.

using UnityEngine.EventSystems;
using UnityEngine.UI;

public class PicoButton: Button
{
    protected override voidAwake()
    {
        base.Awake();
        onClick.AddListener(() => {DoStateTransition(SelectionState.Highlighted, false); });
    }

    public override void OnPointerEnter(PointerEventData eventData)
    {
        base.OnPointerEnter(eventData);
        if (interactable)
        {
            DoStateTransition(SelectionState.Highlighted, true);
        }
    }

    public override void OnPointerExit(PointerEventData eventData)
    {
        base.OnPointerExit(eventData);
        if (interactable)
        {
            DoStateTransition(SelectionState.Normal, true);
        }
    }
}

Similarly, I made a visual display of the improved Button (there is an online experience connection later).

It is worth noting that the implementation here only changes the state visually. In fact, the button currentSelectionStateremains the same (that is, it is pressed or selected), but the Button does not obtain the state interface of this state, so this does not affect our normal interaction.

Finally, attach the button Demo online experience, you can experience the difference between the two:
—-> UguiButtonSelectionStateVisualization

Leave a Comment

Your email address will not be published. Required fields are marked *