Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

"ToggleActive()" callback function for UI components?

Discussion in 'UGUI & TextMesh Pro' started by ryo0ka, Oct 23, 2015.

  1. ryo0ka

    ryo0ka

    Joined:
    Sep 27, 2015
    Posts:
    37
    I found it severely inconvenient that UI components do not have a "ToggleActive()" method.

    Let's say you want to implement a button that toggles some other UI component's visibility state. You would have to prepare two buttons on the top of each other, assigning callbacks like this:

    Button1:
    Something.SetActive(true)
    Button1.SetActive(false)
    Button2.SetActive(true)
    Button2:
    Something.SetActive(false)
    Button2.SetActive(false)
    Button1.SetActive(true)

    Or write a script that does the job taking in a name of the component as a string, which would not be updated when the name is updated later on. Also I prefer not to involve scripts when handling UI behavior.

    If there was a built-in `ToggleActive()` method in UI components, the description can be done like this:

    Button1:
    Something.ToggleActive()

    Just one callback! Isn't this convenient?

    Tell me what you think, and I will appreciate the most if this functionality already exists or can be more easily implemented.
     
  2. fffMalzbier

    fffMalzbier

    Joined:
    Jun 14, 2011
    Posts:
    3,276
    Sounds like a awesome idea, would save some time.

    I checked out the extension methods

    https://unity3d.com/learn/tutorials/modules/intermediate/scripting/extension-methods

    With little code like this you can add (almost) such functionality:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public static class GameObjectExtensions
    5. {
    6.     public static void ToggleActive(this GameObject gameObject)
    7.     {
    8.         // Implementation goes here
    9.         gameObject.SetActive(!gameObject.activeSelf);
    10.     }
    11. }
    Code (CSharp):
    1.   gameObject.ToggleActive();
    The said part is that it does not seem to work with the unity ui event system , it just does not show up.:( Would be nice if it did , Probably it's the wired parameter definition of extension methods"this GameObject gameObject" that makes problems to the eventsystem ui.
     
  3. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    Can't you just use a Toggle instead of a button?
     
  4. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,685
    You're code doesn't show up in the editor @fffMalzbier because it's a static method, the editor doesn't really like those. Only way to make that show up would be to copy the source for the control you wanted it on and add it manually.
    BUT, you could access it via code, by adding a non-static method and have it call the static one, spaghetti mess in code but it should work.

    Yes you could use a Toggle @_Daniel_ as a base. You can use the toggle control like a button using different images for the background and checkbox elements.

    Might also consider making one for the UI Extensions project, seems an interesting control to have.
     
  5. jcredible

    jcredible

    Joined:
    Dec 4, 2012
    Posts:
    24
  6. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,685
    Similar. I'll try and find some time in the morning to give you a better example
     
  7. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,685
    I think I Iost the plot a bit with the original request, lol.
    So yes making a toggle a button style image control placing one image on top of another is fine and having a script like @jcredible 's link which works with the Dynamic bool parameter from the toggle is fine.
    However after re-reading the initial question about SetActive, i don't think that what is what was requested, as it refers to having a factory method in Unity to "toggle" Go's in general on / off.

    You could have a script that simply did:
    Code (CSharp):
    1.     public void UpdateMe (bool value) {
    2.         Something.SetActive(value);
    3.         Something2.SetActive(!value);
    4.     }
    Which would toggle a controls state based on something. but the quest was that instead of SetActive's everywhere, could there be a ToggleActive() function. So @fffMalzbier solution would work but only in code.

    So in short, @ryo0ka , No there isn't a built in ability to do this and you can't do it without code similar to what @fffMalzbier provided to add a code way to apply it. Just have it embedded inside another method / function you can call from the inspector. Like
    Code (CSharp):
    1. public void ToggleActiveState()
    2. {
    3.     gameObject.ToggleActive();
    4. }
    Then attach that where every you need the ability. It's clumsy and would mean the same script would be needed on everything you need to toggle.

    Otherwise, raise a feature request through the Unity Bug reporter in the editor (set the issue type to feature request) and see if anything happens.
     
  8. ryo0ka

    ryo0ka

    Joined:
    Sep 27, 2015
    Posts:
    37
    Thank you @fffMalzbier, @_Daniel_, @SimonDarksideJ and @jcredible for your replies!

    I think my explanation about my idea was not clear enough, so let me describe it here again.
    Let's say we have a UI component, like some pull-down menu or popup panel, and we want to toggle its visibility (on/off) by clicking one button. You click the button once to show the component, and click again to hide it.

    At the moment we are provided two ways to achieve the function:
    1. Place two buttons on the top of each other that represent one of on/off states and assign show/hide callbacks to them
    2. Write a script that toggles the component's on/off state and assign it to the button.

    I briefly described the 1st method in the initial post, but let me do it again here.
    We have two buttons, namely ButtonON and ButtonOFF, and another component (to show/hide) namely Target.
    In order to implement the above behavior, we need to assign some callbacks to them as following:

    ButtonON:
    - Target.SetActive(true)
    - ButtonON.SetActive(false)
    - ButtonOFF.SetActive(true)
    ButtonOFF:
    - Target.SetActive(false)
    - ButtonOFF.SetActive(false)
    - ButtonON.SetActive(true)

    This is too much work to toggle one component's visibility, isn't it?

    About the 2nd approach, one could define a function that takes in a component's name as a string, finds it in the scene and toggles the visibility, or a function that assumes the name or whatever identifier. The problem is that it's not strongly supported by the editor; for example, the name or whatever identifier would not synchronize with rename/replace operations taken on the Unity editor.

    Now if Target had a method `ToggleActive()`, we only need one button (namely Button) to do the same thing:

    Button:
    - Target.ToggleActive()

    Clearly, it makes connections between components much simpler and easier to follow. Also no extra scripting.

    @SimonDarksideJ Yes, I think I will submit this as a feature request, if you think the above explanation is enough to catch their attention, or I would appreciate if you could add something. Thank you again a lot for your support :)
     
  9. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,685
  10. ryo0ka

    ryo0ka

    Joined:
    Sep 27, 2015
    Posts:
    37
    @SimonDarksideJ
    About the 1st option, I tried Toggle but didn't quite get how to make it work as I want. It seems only capable of toggling Image components, while I want to show/hide another button, panel, pulldown menu, etc.

    About the 2nd option, I am told to build the UI in such way that the client wouldn't need to perform any scripting when they desire to arrange the UI components. As long as there is no way to pass a GameObject itself to a callback method as an argument like boolean/int/string values on the Unity editor, they would possibly mess up the connection when they happen to change components' names while the script can't update the referred component's name. So I would like to achieve the toggle functionality without scripting involved, which now makes connections clumsy (for both me and my clients) and I would love to have another method `ToggleActive()` for simplicity. I don't know if Unity expects these use cases (a demand for a button that shows/hides another component, and a client who doesn't want to code while juggling UI at all), but I believe it would be very convenient and save many users' time.
     
    Last edited: Oct 26, 2015
  11. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,685
    If you want to toggle another control / window / etc. then you just need to add that to the inspector events for toggle changed.

    As for the second option, just have the above script attached to a prefab, possibly with a little extra code to automatically wire it up to the OnValueChanged event for the toggle that is meant to control it.

    Don't you just hate "clients" sometimes :D
     
    jcredible likes this.
  12. ryo0ka

    ryo0ka

    Joined:
    Sep 27, 2015
    Posts:
    37
    I got Toggle to work finally. Thank you for your help :)
    Haha they may be watching this, so let me put it like, I don't hate them but sometimes their requests :p
     
    SimonDarksideJ likes this.
  13. Rs

    Rs

    Joined:
    Aug 14, 2012
    Posts:
    74
    Instead of using a "per entity" approach, go with the following:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5. public class MyUIEventManager : MonoBehaviour {
    6.  
    7.     public void ToggleGameObject(GameObject go)
    8.     {
    9.         go.SetActive(!go.activeSelf);
    10.     }
    11.  
    12.     public void EnableGameObject(GameObject go)
    13.     {
    14.         go.SetActive(true);
    15.     }
    16.  
    17.     public void DisableGameObject(GameObject go)
    18.     {
    19.         go.SetActive(false);
    20.     }
    21. }
    22.  
    As usual, attach it to a GameObject, which might be your canvas. The inspector accepts methods with GameObject arguments so you can now add an action in your event, drop your MyUIEventManager object in the slot, set the action method to (example) ToggleGameObject and there you set the GameObject you want to toggle. This allows you to toggle, enable, disable, without writing bits of code for every entity which would lead to some tedious "ToggleThis", "ToggleThat", "ToggleMario", "ToggleLuigi".
     

    Attached Files: