@VTheDrago0nS
For your current case (different menus for your game) the statemachine thing suggested by @Stardog is probably the best solution.
It is powerful, clean, and it leaves the door open for custom handling of state changes later on!
However it might not be the most time-efficient thing you can do! 
A statemachine setup is more up-front work and more work to maintain.
And if you’re just making a small game, it might not be worth the time investment.
Your initial approach can be improved a lot in just a few steps!
First step:
Lets deal with the ‘boring’ indexing into arrays.
public void GoBackToMainMenu()
{
myPanels[3].SetActive(false);
myPanels[2].SetActive(false);
myPanels[1].SetActive(false);
myPanels[0].SetActive(true);
}
Adding cases (lines) for each new panel will get boring quick, instead you could do:
public void SwitchTo(int panelIndex)
{
for(int i = 0; i < myPanels.Length; i++)
p.SetActive(panelIndex == i);
}
This is a more optimized variant of what stardog also suggested. (turning off all, then turning on the one you want).
Next step:
Addressing those panels will quickly become very hard, especially once you realize you might want to dynamically load more panels. Maybe plugins have their own panel? Or the user can open “windows” like an inventory or so…? So numbers are out.
Maybe you could give each panel a name and then activate them by their name?
Like SwitchTo("mainMenu");
and inside the function p.SetActive(p.name == switchToName)
instead of comparing the index…
But strings can have typos, so that’s still not good. So generics to the rescue!
You most likely already have a sort of “controller” on each panel that wires up all the components with each other, so that one can be used to address the menu without any ambiguity (and autocomplete in vs!)
interface IMenuPanel { } // marker interface
class MainMenuPanel : IMenuPanel { ... }
class OptionsPanel : IMenuPanel { ... }
...
public void SwitchTo<TMenu>() where T : IMenuPanel
{
foreach(var p in myPanels)
p.SetActive(p.GetComponent<TMenu>() != null);
}
// switch to main menu
SwitchTo<MainMenu>();
The generic constraint on the method (where T : IMenuPanel
) ensures that you can’t accidentally use a type that isn’t actually a menu panel.
Next, composition:
Nice, but we can tack on a few more minor things to make this much more powerful.
- Instead of manually populating an array or list of panels, we can now just do something like this
- In SwitchTo we should also return the component so that we can use it immediately.
public TMenu SwitchTo<TMenu>() where T : IMenuPanel
{
TMenu menuComponent = null;
foreach(var p in myPanels)
{
var c = p.GetComponent<TMenu>();
if(c != null)
{
menuComponent = c;
p.SetActive(true);
}
else
{
p.SetActive(false);
}
}
return menuComponent;
}
// assuming your game has an options panel that has a few tabs
// inside it for each category (video, audio, gameplay, ...):
SwitchTo<OptionsPanel>()?.SelectTab(OptionTabs.Audio);
- From here we can build even more stuff ontop!
Maybe some logging when the menu wasn’t found? To improve startup time: maybe SwitchTo
can instantiate each panel as it is requested, instead of having them all loaded from the start? …