2
\$\begingroup\$

I'm trying to figure out how I can make a custom UI element identify when it has been selected or deselected. Classes such as Selectable inherit from the ISelectHandler and IDeselectHandler and their methods OnSelect() and OnDeselect() are called whenever I click inside the Selectable element and click outside of it.

From my understanding, inheriting from the appropriate handler interface and implementing it's required method will allow your class to handle events from the EventSystem. As an example if I have:

public class TestSelectable
    : MaskableGraphic,
    ISelectHandler,
    IDeselectHandler,
    IPointerEnterHandler,
    IPointerExitHandler
{

    public void OnSelect(BaseEventData eventData)
    {
        Debug.Log("Selected");
    }

    public void OnDeselect(BaseEventData eventData)
    {
        Debug.Log("De-Selected");
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        Debug.Log("Pointer Enter");

    }

    public void OnPointerExit(PointerEventData eventData)
    {
        Debug.Log("Pointer Exit");

    }

When the mouse enters and exits the element the OnPointerEnter() and OnPointerExit() methods are sucessfully called. However selecting/De-selecting the element does not cause the OnSelect() or OnDeselect() methods to be called. Though if you look in InputField.cs (which inherits from Selectable), the OnSelect() method does successfully get called when the input field is selected. I'm trying to replicate this within my own element without having to inherit from Selectable, and since Unity's event system is publicly accessible this should be possible.

Are there other requirements that will enable those events to fire and call my methods?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

I managed to figure this out. You need to manually tell the EventSystem that the object has been selected. On a method such as OnPointerDown() you need to call the EventSystem.current.SetSelectedGameObject() method and pass in the event data and your gameobject.

public class SelectableText
    : MonoBehaviour,
    IEventSystemHandler,
    ISelectHandler,
    IDeselectHandler,
    IPointerDownHandler,
    IUpdateSelectedHandler
{

    public void OnPointerDown(PointerEventData eventData)
    {
        if (eventData.button != PointerEventData.InputButton.Left)
            return;

        // Selection tracking
        EventSystem.current.SetSelectedGameObject(gameObject, eventData);
    }

    public void OnSelect(BaseEventData eventData)
    {
        //base.OnSelect(eventData);
        UnityEngine.Debug.Log("Selected");
        isFocused = true;
    }

    public void OnDeselect(BaseEventData eventData)
    {
        //base.OnDeselect(eventData);
        UnityEngine.Debug.Log("De-Selected");
        isFocused = false;
    }

If you have inherited from ISelectHandler and IDeselectHandler the OnSelect() method will be called, and if you click off of your UI element onto the background or another UI element the OnDeselect() method will be called.

\$\endgroup\$
2
\$\begingroup\$

Ran into the same situation myself recently and try as I might I never got the event to fire off. I'm guessing Selectable does some kind of initialization with the Event System, maybe adding the game object to a list of selectable objects or maybe checking the Input Position versus the graphic the control contains etc...

But you can get around this simply by adding the Selectable script to the game object your TestSelectable script is attached to. Once you do that then you will begin recieving OnSelect() and OnDeselect(). You can automate this by adding the line: [RequireComponent (typeof (Selectable))] at the top of your script, leaving you free to still derive from MaskableGraphic.

\$\endgroup\$
1
  • \$\begingroup\$ Oh, I need to answer this question. I'm trying to go about this without inheriting from selectable, so I can inherit from maskable graphic. Unity's documentation for most of their UI stuff is pretty bad, but I managed to figure it out by digging around their source code. You need to add a line of: EventSystem.current.SetSelectedGameObject(gameObject, eventData); to a method such as OnPointerDown which comes with PointerDownHandler \$\endgroup\$ Commented Jun 7, 2015 at 16:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .