Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Agent654 · Oct 12, 2015 at 03:45 PM · uibuttonstateinteractable

How to detect interactable state change in selectable objects (Buttons, etc.)

Pitching this one out there to the community - let's say, for the sake of argument here, I have a button on-screen.

I have some additional behaviors that I'd like to trigger upon changing a selectable GUI control's interactable state. I don't want to disable the button object, but I do want to change it's text color, for example, when the button becomes non-interactable.

I understand that I could just test to see if the interactable boolean has changed within the update loop, and trigger off of that - but I really don't think this would be the optimal way to do so, considering multiple buttons would likely be pounding the crap out of the Update loop in the process, needlessly checking for its state change.

I also understand that I could write a custom function that performs these actions in addition to setting that variable - but I was hoping to have it more reactive to the state, rather than driving it.

Does anyone have some suggestions or tips on how I might achieve this sort of detect-and-react approach? Or should I just begin writing my custom function to handle this?

Thanks for any suggestions!

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by dkjunior · Oct 13, 2015 at 03:26 AM

Not exactly the answer to your question, but you can customize button's appearance in non-interactable state using Transitions. Check them out in the inspector. If color change is all you need than it's pretty simple - keep the default Color Tint transition type and change the Disabled color property (which corresponds to non-interactable state). You can customize appearance even further by selecting Sprite Swap or Animation transition types.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Agent654 · Oct 13, 2015 at 03:53 PM 0
Share

@dkjunior - I understand the color tint/sprite state change stuff - this was more speaking to a custom composition of a GUI button that includes labels & icons, and when the button turns interactable off, then the idea would be to change the label color to a disabled color as well as changing the icon asset's alpha or something ...

Was just hoping there'd be an integrated event or function that triggers upon that interactable boolean's value change.

Thanks for the input.

avatar image dkjunior Agent654 · Oct 13, 2015 at 06:22 PM 2
Share

There's a way to do that through extending the classes you want. Warning: in many cases it may be an overkill, but if you want to add substantial amount of custom logic, this may be an elegant way to go.

 public class $$anonymous$$yButton : Button {
 
     public event Action<bool> InteractableChanged;
 
     public bool $$anonymous$$yInteractable
     {
         get
         {
             return interactable;
         }
         set
         {
             if (value != interactable)
             {
                 interactable = value;
                 OnInteractableChanged(interactable);
             }
         }
     }
 
     protected void OnInteractableChanged(bool interactable)
     {
         if (InteractableChanged != null)
             InteractableChanged (interactable);
     }
 }

Obviously, you would want to choose better names than $$anonymous$$yButton & $$anonymous$$yInteractable.

avatar image Agent654 dkjunior · Oct 13, 2015 at 07:21 PM 0
Share

Nice - good point! Thanks, this is definitely something I'll investigate!

avatar image
6

Answer by free-divbyzero · Apr 06, 2016 at 11:41 AM

Hi.

Try this.

 public class MyButton : Button
 {
     protected override void DoStateTransition(SelectionState state, bool instant)
     {
         if (state == SelectionState.Disabled)
         {
 
         }
         else if (state == SelectionState.Normal)
         {
             
         }
     }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by JoshuaMcKenzie · Oct 13, 2015 at 11:30 AM

typical rule of thumb I go by is that other game objects shouldn't know that a UI even exists (unless its also a UI and only if there's no better way). This rule of thumb is there to help prevent deadlocks in logic behavior, or some nasty hard to trace bugs.

For example, I wouldn't have my AudioController ask if the UI mute button is turned on or off, I do it the other way around... my AudioController tracks the mute state and the button checks what state the mute is. If muted show the unmute icon, otherwise show the mute icon. when the button is pressed it triggers a call to the AudioController to change its state via a public function in the AudioController. The AudioController has no knowledge whatsoever that a mute button even exists, nor does it need to.

so to answer your question, I would instead have whatever you have checking to state of the button check the source of what ever is affecting that button's state. if the logic you have that determines the state of the button self contained in the script connected to the button, I would push it out to an external controller class.

And in this external class set the state change to an event so what ever needs to work of it can just subscribe themselves to the event. This will further decouple your code (classes know less about other classes and thus are less prone to break from code changes) and keeps it fast (instead of having to ask that class every frame what it's state is, the class will simply tell all that cares to listen when it's state has changed).

I don't know exactly what you need to track the button state, but this is how I would code it, going back to my previous example....

     public class AudioController : Monobehavior
     {
         public delegate void MuteEvent();
         public static event MuteEvent OnMute;
         public static AudioController instance;
     
         private bool _isMuted = false;
         public bool IsMuted
         {
               get { return _isMuted;}
               set
               {
                      _isMuted = value;
 
                      // only call if someone is listening, 
                      // otherwise you'll get a crash 
                      if(OnMute!=null) 
                      {
                             OnMute();
                      }
               }
         }
     
         void Awake()
         {
               // set the static reference so that other 
               // scripts don't have to do any complex searching
               instance = this;
         }
     }
     
     public class MuteButtonScript : Monobehavior
     {
             public Button btn;
             public Sprite muteSprite;
             public Sprite unmuteSprite;
     
            void Awake()
            {
                   Button btn = GetComponent<Button>();
            }
            void OnEnable()
            {
                   //subscribe to the AudioController's On Mute event
                   AudioController.OnMute += OnMute;
            }
            void OnDisable()
            {
                   //unsubscribe from the AudioController's On Mute event
                   AudioController.OnMute -= OnMute;
            }
 
           // this function will always run whenever the class is subscribed 
           // to the AudioController and the AudioController runs "OnMute()"
           void OnMute()
           {
                  //update the button sprite depending on the AudioController's Mute State
                  btn.image.sprite = AudioController.instance.IsMuted ? muteSprite : unmuteSprite;
           }
     }

here the button's image is changing state depending on when the AudioController issues the OnMute event. So instead of having whatever you're planning to listen to this button, have it listen to the event from the audio controller. Neither the AudioController nor the MuteButtonScript needs to know what this script is, which makes it very easy and lightweight to extend functionality.

by using events you can have other classes (subscribers) attach themselves to an event that is issued by a single source (provider) and the subscribers don't have to constantly check every update loop, the provider simply tells the subscribers when the event happens.

so whatver event that is causing your button to become non-interactible have your other UI stuff also listen to that same event and have then change their color based on the same decision making

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Agent654 · Oct 13, 2015 at 03:50 PM 0
Share

This is where my train of thought was taking me, I figured I'd make a custom function attached to the GUI object itself that another function/object can simply call (or even use the event/delegate system) to trigger those types of changes.

The idea was that the font color, and image assets attached to the GUI button would flip to their "disabled" states under those circumstances.

I was just fishing out to see if there was a function or something that triggers on change of the "interactable" boolean state (kind of like the OnEnable/OnDisable functions).

Thanks for the input though - I think I'll likely go the route of making a function that is present on most GUI objects that can simply be called to handle these nuances.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

40 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Making a button appear on a specific state? 1 Answer

UI Buttons Interactable switch 1 Answer

Callback when 'interactable' is toggled on a UI button? 0 Answers

Play sound on noninteractable / disabled / grayed out button 1 Answer

UI Button not working 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges