Reading / getting events from Selectable's currentSelectionState (hover, pressed, normal...)

I want to get events from UI elements when they are hovered over, pressed, disabled (directly or indirectly due to CanvasGroups), etc…

I could inherit from Selectable, but then I’d either:
a) inherit directly from Selectable, preventing the use of existing functionality from Scrollbar, Button, Toggle, etc., or
b) inherit from the derived Selectable classes, which means my custom class would have to be duplicated to inherit from each one.

The only other option I see is to make a new component that inherits from UIBehaviour (in order to get OnCanvasGroupChange calls), and that implements IPointerDownHandler, IPointerExitHandler, etc., then calculates its state, and raises events when that state changes… which is basically exactly what Selectable does, so it’s a shame to not use that existing functionality.

I think that Selectable should make its currentSelectionState property public, and should have public events for when currentSelectionState changes. It’s not like this information is being hidden: you can currently access the state by attaching an Animator component, hooking it up to the Selectable through the animation trigger transition type, then have the Animator animate a value representing the Selectable’s state, or have it use Animation Events. But that’s ridiculous.

As for my use case, I’m trying to make reusable animations for UI elements: colour change, transform scale change, fade, etc… You can’t make reusable animations with Mecanim if the users of the animation have different hierarchy structures (a scrollbar might be set up differently than a button, tab, or checkbox) - nevermind that Mecanim is complete overkill for small animations like fading a button. So I arrived at this problem when trying to send interaction events to a scripted animation system.

I don’t think that is a very specific case - anyone making at least a medium-sized UI system with any form of visual effects would want reusable animations for UI elements.

I was running into a similar issue. I generalized the question for possible post on stack-exchange, but may have come upon a possible answer. Let me know what you think.

These classes (pseudo-code - most function bodies not shown) exist in the 3rd party library I’m using. I cannot change them:

Class Fruit:LibraryBaseObject{Eat();}
Class Bananna:Fruit{Peel();}
Class Apple:Fruit{MakeJuice();}
Class Cherry:Fruit{Pop();}
Class Fig:Fruit{Poop();}
Class Pear:Fruit{WeebleWobble();}
Class Tomato:Fruit{Really();}
Class Stawberry:Fruit{Fields();}

I want to add a variable and function to the Fruit class, and override the Eat function.

Class FruitWithSeeds:Fruit
{
   int number_of_seeds;
   DeSeed();
   override Eat(){DeSeed();base.Eat();}
}

But since I cannot change the definition of an Apple, Pear, etc… I’m not sure how to define/redefine all my fruits to be FruitsWithSeeds.

This is the best solution I could come up with, but I don’t really like it…

Satic class FruitWithSeedFunctions // a single definition of the extended functions
{
   DeSeed(Fruit f,int numSeeds);
   Eat(Fruit f,int numSeeds){DeSeed(f,numSeeds);f.Eat();}
}

Class BanannaWithSeeds:Bananna
{ //the following WILL still need to be redefined/duplicated for each type of fruit
   int number_of_seeds;  
   override Eat(){return FruitWithSeedFunctions.Eat(this,number_of_seeds);}
}


Class AppleWithSeeds:Apple
{ 
   int number_of_seeds;  
   override Eat(){return FruitWithSeedFunctions.Eat(this,number_of_seeds);}  
}

Yeah, I think that’s a general thing in programming that you can’t do easily, which is why I’m suggesting that Unity makes changes on their end.

The solution I used worked well enough - I made a component that inherits from UIBehaviour, with public events for mouse hover, mouse press, interactable, etc., and basically used that instead of Unity’s Selectable components.

An alternative solution that may or may not work here is to use a custom EventSystem and just route any relevant calls to your “TransitionManager” or whatever-you-have class. Not the most graceful solution in this case perhaps, but figured it worth a mention if only for future Googlers.

Did anybody get a better solution to this? Having the same problem and it’s a little strange that we can’t access these states. How else are we to play hover, click, release sounds, etc?

Hi Matthew,

You can still collect those events by implementing the IHandler classes, like IPointerDownHandler, IPointerExitHandler, etc.
The issue the OP has, and I do too, is the fact that you need to re-define these handler functions for each class you create. If we could change the definition of the Selectable class, from which all the UI controls are descended, we would only need to do this once, rather than for each class. But we can’t.