(de)Activating UI Panels using SetActive(bool)

I am having trouble activating my UI panels after deactivating them. All the menus deactivate with no problem. But it seems like once deactivated there’s no way of getting them back. Using either Find(object).SetActive(true) or Find(object).gameObject.SetActive(true) led to no avail.

ERROR: NullReferenceException: Object reference not set to an instance of an object

Am I using the wrong technique? Below is my MenuManager class:

public class MenuManager : MonoBehaviour {
    
    	public int menuID=0;
    	public GameObject[] menuPanels;
    
    	// Use this for initialization
    	void Start () {
    		menuPanels = GameObject.FindGameObjectsWithTag("MenuPanel");
    	}
    
    	public void switchToMenu(int menuID) {
    
    		foreach(GameObject panel in menuPanels)
    		{
    			panel.gameObject.SetActive(false);
    			Debug.Log (panel.name);
    		}
    
    		switch (menuID) {
    			case 0:
    				GameObject.Find("MainMenuPanel").SetActive(true);
    				break;
    			case 1:
    				GameObject.Find("OptionsPanel").SetActive(true);
    				break;
    			case 2:
    				GameObject.Find("CharacterSelectPanel").SetActive(true);
    				break;
    			case 3:
    				GameObject.Find("GameModePanel").SetActive(true);
    				break;
    			case 4:
    				GameObject.Find("ModsPanel").SetActive(true);
    				break;
    			case 5:
    				GameObject.Find("StageSelectPanel").SetActive(true);
    				break;
    		}
    	}
    }

I discovered my own answer. You cannot do a Find(object) on something that is already deactivated. You will need to gather those objects before hand then reference them through a variable like below:

public class MenuManager : MonoBehaviour {

	public int menuID=0;
	public GameObject[] menuPanels;
	private GameObject mainMenuPanel;
	private GameObject optionsPanel;
	private GameObject characterSelectPanel;
	private GameObject gameModePanel;
	private GameObject modsPanel;
	private GameObject stageSelectPanel;

	// Use this for initialization
	void Start () {
		menuPanels = GameObject.FindGameObjectsWithTag("MenuPanel");

		mainMenuPanel = GameObject.Find("MainMenuPanel");
		optionsPanel = GameObject.Find("OptionsPanel");
		characterSelectPanel = GameObject.Find("CharacterSelectPanel");
		gameModePanel = GameObject.Find("GameModePanel");
		modsPanel = GameObject.Find("ModsPanel");
		stageSelectPanel = GameObject.Find("StageSelectPanel");

//		int playerNum = PlayerInfo.playerID;
//		Debug.Log (playerNum);
		switchToMenu (menuID);
	}
	
	// Update is called once per frame
	void Update () {

	}

	public void switchToMenu(int menuID) {

		foreach(GameObject panel in menuPanels)
		{
//			panel.gameObject.renderer.enabled=false;
			panel.gameObject.SetActive(false);
			Debug.Log (panel.name);
		}

		switch (menuID) {
			case 0:
			mainMenuPanel.gameObject.SetActive(true);
				break;
			case 1:
			optionsPanel.gameObject.SetActive(true);
				break;
			case 2:
			characterSelectPanel.gameObject.SetActive(true);
				break;
			case 3:
			gameModePanel.gameObject.SetActive(true);
				break;
			case 4:
			modsPanel.gameObject.SetActive(true);
				break;
			case 5:
			stageSelectPanel.gameObject.SetActive(true);
				break;
		}
	}
}

If possible, it’s always good to prevent from using any GameObject.Find. They are very slow. You only use it in Start, so the problem is indeed limited. You could also mark them as public and set them from the editor, you will not need to “Find” them anymore.

Also, a good way to activate panels is to use the CanvasGroup. Add the CanvasGroup component to your panel (in layout menu).
To activate a panel: set alpha to 1 and ‘interractable’ to true. Reverse that to deActivate them.

I had the same problem, found the above answer helpful, but then found another way to do this:

You can use FindChild(“child name”).gameObject to get an inactive gameobject as long as you can find the parent easily enough. In my case, I ended up with this code in order to set an inactive child active:

GameObject gameOverParent = GameObject.Find("HUDCanvas");
		GameObject gameOver = gameOverParent.transform.FindChild("GameOver").gameObject;
		gameOver.SetActive(true);

Just leaving this here in case it helps someone out some day.

There is an asset called Woo Panels. It does exactly what you are tring to achieve. Check it out! Here is the forum thread.