"ToggleActive()" callback function for UI components?

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.

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:

using UnityEngine;
using System.Collections;

public static class GameObjectExtensions
{
    public static void ToggleActive(this GameObject gameObject)
    {
        // Implementation goes here
        gameObject.SetActive(!gameObject.activeSelf);
    }
}
  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.:frowning: 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.

Can’t you just use a Toggle instead of a button?

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.

@SimonDarksideJ - I wasn’t completely following the TC’s post. Do you mean something like this: Toggle button - Unity Engine - Unity Discussions

Similar. I’ll try and find some time in the morning to give you a better example

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:

    public void UpdateMe (bool value) {
        Something.SetActive(value);
        Something2.SetActive(!value);
    }

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

public void ToggleActiveState()
{
    gameObject.ToggleActive();
}

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.

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 :slight_smile:

OK, so you can achieve option 1: using the toggle as a button as described above.
You can also achieve option 2 by using the method I describe ("ToggleActive()" callback function for UI components? - Unity Engine - Unity Discussions) and hook it up to the inspector for the toggle. Because the new UnityEvent system allows you to add multiple events in the editor

@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.

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 :smile:

1 Like

I got Toggle to work finally. Thank you for your help :slight_smile:
Haha they may be watching this, so let me put it like, I don’t hate them but sometimes their requests :stuck_out_tongue:

1 Like

Instead of using a “per entity” approach, go with the following:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class MyUIEventManager : MonoBehaviour {
  
    public void ToggleGameObject(GameObject go)
    {
        go.SetActive(!go.activeSelf);
    }

    public void EnableGameObject(GameObject go)
    {
        go.SetActive(true);
    }

    public void DisableGameObject(GameObject go)
    {
        go.SetActive(false);
    }
}

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”.

2858987--209136--Example.png