I have a menu that gets populated at runtime with buttons whose text components are based on objects that the game manager has in its databases. At the start, the menu is empty:
See that "A" graphic? It's a button called Button_Magic_DropDown that activates/deactivates the panel called Panel_MagicMenu. At runtime, regardless of whether the panel is active, its child panel Empty_Inset_MagicMenu gets 6 children, which are all instances of the button prefab, Button_BattleMenu. When one of these buttons are clicked, I want the panel called Panel_MagicMenu to get deactivated. See image below:
What I am struggling with is deactivating [the parent panel of a ] panel that a button sits in when it is clicked. I am trying to do this by getting the second parent programmatically and deactivating it. Here is the script containing that function OnClickDeactivatePanel(), which I am assigning in the button prefab:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BattleUI : MonoBehaviour
{
public void ToggleActive(GameObject panel)
{
panel.SetActive(!panel.activeInHierarchy);
}
public void OnClickDeactivatePanel()
{
//On click, deactivates the panel that the button sits in, two parents up
GameObject secondParent = gameObject.transform.parent.parent.gameObject;
//Debug.Log("Second parent is " + secondParent);
secondParent.SetActive(false);
}
}
As you can guess, this didn't work. Unity is unable to identify the parents of an instanced object this way. I get a null-reference error. What can I do?
Here is the button prefab, Button_BattleMenu, if it helps:
This is obviously an encapsulation issue. The buttons are cloned into the menu during an Awake() function in another script.
EDIT: Changing Awake() to OnEnable() and OnStart() didn't work, but I appreciate the help. Here is the script that loads the buttons (you can see I have an impending decoupling problem on my hands:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class _CharStatManager : MonoBehaviour
{
public float scaleFactor = 0.75f;
public float resolution = 100f;
[SerializeField] GameObject entry;
private TMP_Text tmpText;
// MAGIC
public List<SpecialAttack> magicList = new List<SpecialAttack>();
private uint magicList_size;
[SerializeField] GameObject magicContainer;
[SerializeField] GameObject magicContainerParent;
// ITEM
public List<Item> itemList = new List<Item>();
private uint itemList_size;
[SerializeField] GameObject itemContainer;
[SerializeField] GameObject itemContainerParent;
// ATTACK
[SerializeField] GameObject attackContainer;
[SerializeField] GameObject attackContainerParent;
//DEFENSE
[SerializeField] GameObject defenseContainer;
[SerializeField] GameObject defenseContainerParent;
void Awake()
{
//Don't Destroy:
DontDestroyOnLoad(this.gameObject);
float multiplier = Mathf.Pow(resolution * scaleFactor,-1);
//=================================================================
//=================================================================
//+==================================+
//|$$$$$$$$$$$ MAGIC MENU $$$$$$$$$$$|
//+==================================+
//Populate list of all Special Attacks (magic)
magicList.Add(new SpecialAttack("Jump", -15, -2,SpecialAttack.Types.PhysDamage));
magicList.Add(new SpecialAttack("Fireball", -15, -2,SpecialAttack.Types.Fire));
magicList.Add(new SpecialAttack("Super Jump", -20, -5, SpecialAttack.Types.PhysDamage));
magicList.Add(new SpecialAttack("Super Flame", -20, -5, SpecialAttack.Types.Fire));
magicList.Add(new SpecialAttack("Ultra Jump", -25, -8, SpecialAttack.Types.PhysDamage));
magicList.Add(new SpecialAttack("Ultra Flame", -25, -8, SpecialAttack.Types.Fire));
magicList_size = (uint)magicList.Count;
float buttonHeight = entry.GetComponent<RectTransform>().sizeDelta.y;
/*This is where it gets tricky: Need to expand the height of the
* magic menu "container" before we instantiate more buttons.
* Those buttons will be offset automatically thanks to Vertical Layout Group component.*/
// Resize Container:
float magicContainerHeight = magicContainerParent.GetComponent<RectTransform>().sizeDelta.y;
float magicTargetHeight = magicContainerHeight + buttonHeight * (magicList_size - 1);
magicContainerParent.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, magicTargetHeight);
// Instantiate children of Container (Vertical Layout Group component will take care of alignment for me)
for (int i = 0; i < magicList_size; i++)
{
GameObject newMagicButton = Instantiate(entry, magicContainer.transform, false);
newMagicButton.GetComponentInChildren<TMP_Text>().text = magicList[i].menuName;
}
//=================================================================
//=================================================================
//+==================================+
//|$$$$$$$$$$ DEFENSE MENU $$$$$$$$$$|
//+==================================+
GameObject newDefenseButton = Instantiate(entry, defenseContainer.transform, false);
newDefenseButton.GetComponentInChildren<TMP_Text>().text = "Defend";
//=================================================================
//=================================================================
//+===================================+
//|$$$$$$$$$$$ ATTACK MENU $$$$$$$$$$$|
//+===================================+
PhysicalAttack onlyAttack = new PhysicalAttack("Punch Glove", -10);
GameObject newAttackButton = Instantiate(entry, attackContainer.transform, false);
newAttackButton.GetComponentInChildren<TMP_Text>().text = onlyAttack.menuName;
//=================================================================
//=================================================================
//+=================================+
//|$$$$$$$$$$$ ITEM MENU $$$$$$$$$$$|
//+=================================+
//Populate list of items (magic)
itemList.Add(new Item("HP Shroom","Recover 30hp."));
itemList.Add(new Item("Power Star","Strength + 3"));
itemList.Add(new Item("Chocolate Mousse","A treat you shouldn't keep to yourself."));
itemList_size = (uint)itemList.Count;
// Resize Container:
float itemContainerHeight = itemContainerParent.GetComponent<RectTransform>().sizeDelta.y;
Debug.Log(itemContainerHeight);
float itemTargetHeight = itemContainerHeight + buttonHeight * (itemList_size - 1);
Debug.Log(itemTargetHeight);
itemContainerParent.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, itemTargetHeight);
// Instantiate children of Container (Vertical Layout Group component will take care of alignment for me)
for (int i = 0; i < itemList_size; i++)
{
GameObject newItemButton = Instantiate(entry, itemContainer.transform, false);
newItemButton.GetComponentInChildren<TMP_Text>().text = itemList[i]._menuName;
}
}
}