Turn off everything else in Canvas

I have around 20 buttons which each activate their own panel (with text and such as children).

All these buttons are visible at the same time, so Users are likely to tap one button then tap another button without closing the panel in between.

So what I want to do is: Tap button > Show panel…also turn off all other panels.

I can do this in a very manual way of assigning each panel and SetActive on each button press but I want a more efficient way of doing it.

I also considered using Tags, but then it would turn off the panel that I want on as well.

Depends on how you are doing this. Is the sub-menu a separate Canvas? If so, you can turn off the Graphic Raycaster on the main Canvas. The Buttons will still be visible but you won’t be able to click on them.

If you are dynamically creating a panel on the existing canvas then you can turn buttons off en-masse using this code:

        Button[] buttons = canvas.GetComponentsInChildren<Button>();
        foreach (var but in buttons)
        {
            but.interactable = false;
        }

The variable canvas is a serialised (or public) field and you drag the Canvas gameobject into the exposed box in the Inspector. You can use similar code to turn all the buttons back on again when you close your sub-menu.

OK. Let’s try this. I assume you are using the standard Unity Events for your buttons. If not, you may have to modify this a little.

You are to write two scripts as follows:

using UnityEngine;
using UnityEngine.UI;

public class UIManager : MonoBehaviour
{
    [SerializeField] Canvas canvas;

    public void ButPress(Button button)
    {
        Button[] buttons = canvas.GetComponentsInChildren<Button>();
        foreach (Button but in buttons)
        {
            but.interactable = !interactable;
        }

        ButtonID targetButton = button.GetComponent<ButtonID>();
        targetButton.ID();
    }
}



using UnityEngine;
using UnityEngine.UI;

public class ButtonID : MonoBehaviour
{
    public void ID()
    {
        Button myButton = this.gameObject.GetComponent<Button>();
        myButton.interactable = true;
    }
}

The first script goes in an empty GameObject called ButtonManager or something like that. Every button has its OnClick pointing at that script in ButtonManager. It turns every button to non-interactable then it calls the second script on the button it received as an argument.

Whether every button has a unique script or a common one is up to you but it should include the public script number 2 above (I’ve called it ButtonID with a method called ID since my testing simply printed the Button name). That second script turns itself to interactable and can go on to display the sub menu.

That’s the basics of it. I don’t know how you are creating or hiding your sub-panel so there may be some wrinkle there but the first script can turn all buttons back on again. There’s a little for you to think about but this should work on the whole. My testing worked fine…

Each button needs to identify itself to the OnClick. You can see I’ve dragged the Button 3 GameOBject into the OnClick parameter box below.

201175-screenshot-2022-10-26-at-175333.png

I’ve come up with a solution that works with one 1 short script.

It finds all GameObjects with the tag “InfoBox” and turns them off except the Panel that I assign in the Inspector.
I apply this to each button and assign the corresponding Panel and that seems to work well.

It also means I can add more buttons and panels without the need to add it to a script.

    public GameObject PresentInfo;
      List<GameObject> gos = new List<GameObject>();

public void PresentMarker(){
PresentInfo.SetActive(true);
         foreach (GameObject go in GameObject.FindGameObjectsWithTag ("InfoBox")) {
            go.SetActive(false);
             if (go.Equals(PresentInfo))
             PresentInfo.SetActive(true);
                 continue;
             gos.Add(go);
         }
     }