- Home /
Extremely confused with parent and child object system
So I was trying to understand the build mechanics for my game instead ended up having lots of questions about child and parent objects system. The script works fine but doesn't makes sense to me.
I will try to explain what I was trying to do:
I have a prefab called m_slot which has a parent gameobject with rect transform and a child gameobject with button.
I have some sprites for sprite array
And a menu gameobject
This script is on Organelle Menu
It instantiates a slot and sets the parent to menu
But when I try to reach to the button gameobject it gets Slot with the name of the sprite which is for example "ribosome" (I noticed it by printing the name)
Here is what I thought it should be like
The _button should be the button game object instead it is Slot game object
So that I shouldn't be writing this
_button.GetComponentInChildren().sprite = m_slotIcon[i]; _button.GetComponentInChildren().onClick.AddListener(OnClick);
but this
_button.GetComponent().sprite = m_slotIcon[i]; _button.GetComponent().onClick.AddListener(OnClick);
And I thought adding OnClick() function to the button would be the Button gameobjects function so when a I call its parent name it would give me the name of the slot which is "ribosome" for example
public class OrganelleMenu : MonoBehaviour {
public GameObject m_slot;
public Sprite[] m_slotIcon;
private Transform m_menu;
private void Awake()
{
m_menu = GameObject.FindGameObjectWithTag("OrganelleMenu").GetComponent<Transform>();
}
private void OnEnable()
{
for (int i = 0; i < m_slotIcon.Length; i++)
{
GameObject _slotInstance = Instantiate(m_slot, transform.position, Quaternion.identity); //Instantiate slot
_slotInstance.transform.SetParent(m_menu.transform); //change slot parameters
_slotInstance.transform.localScale = new Vector3(1, 1, 1);
_slotInstance.name = m_slotIcon[i].name;
GameObject _button =_slotInstance.GetComponentInChildren<Transform>().gameObject;
Debug.Log(gameObject.name);
Debug.Log(_button.name);
_button.GetComponentInChildren<Image>().sprite = m_slotIcon[i];
_button.GetComponentInChildren<Button>().onClick.AddListener(OnClick);
}
}
void OnClick()
{
string _organelleName = GetComponentInParent<Transform>().name;
Debug.Log("Clicked " + _organelleName);
}
}
Any missing information please tell me. I have limited English knowledge. Tried my best
Answer by SirPaddow · Nov 02, 2019 at 08:29 PM
GetComponentInChildren will search for the component in the gameObject itself, then in its children and so on (https://docs.unity3d.com/ScriptReference/Component.GetComponentInChildren.html)
So, on line 20, when you try to get the Transform component on your children, you actually get the transform of "Slot" itself.
Assuming Slot does not have the "Button" component, you could fix it like this:
Button _button =_slotInstance.GetComponentInChildren<Button>();
Debug.Log(gameObject.name); // will still display "Slot"
Debug.Log(_button.name); // will display "Button"
_button.GetComponent<Image>().sprite = m_slotIcon[i];
_button.onClick.AddListener(OnClick);
So all the getComponent commands(getComponentInParent, getComponentInChildren) are based on depth first search, right?
And is there any way to search for a specific component in childrens without the tags. For example:
We have a empty gameobject and 3 child objects
But I want to reach to the third objects component
I don't know all of them, but your two examples are indeed depth first search.
You can find most "strutcure" functions on the Transform Component (which all gameobjects have). As for your exemple, you could use GetChild like this:
Transform my3rdChild = myGameObject.transform.GetChild(2);
I try to never use this kind of function though, because it's subject to so many errors. If in one month, you have to add a new child at the first position, this script won't work anymore and it will take a while to understand why. In your first example, I would create a "Slot" monobehaviour with a reference to the button, and assign this button through the inspector. It means that once my script is done, I will never have to come back to it anymore, and create any structure I want in Unity.
So you mean drag and drop method from the inspector is better than scripting.
I really appreciate the help. It really helped me understand better.
And before I forget, my approach with this kind of script was a more procedural method so that I won't need to worry about finding the components and so on. I wanted to just fill the array with the desired type and than the script will do the magic. But I guess there is no or at least I don't know how to, yet.
Your answer
Follow this Question
Related Questions
Rotate Child with parent, keeping Child axis in the original direction 2 Answers
Make child's transform independent of parent 1 Answer
Snaping/Merging game objects together 0 Answers
Enabling/Deactivating objects using keys. 1 Answer
Why Deparenting The First Child Changes Position of The Parent 0 Answers