Reputation: 31
as I know that to get the top most parent is transform.root
.How about if I want to get the bottom most child and in the condition that I don't know the child name?I have try
for (int i=0; i<theParent.childCount; i++)
{
int bottommost=theParent.childCount-1;
Debug.Log(theParent.GetChild(bottommost).name);
}
But is not the result I expect,I just get the first child but I want the bottom most one.I mean the bottom most child in a hierarchy by the way.Is that any tips to get the most bottom child?Thanks.
Upvotes: 2
Views: 14843
Reputation: 100
Any child could have some children and it can continues interminably. @Caribenz mentioned this. So I propose the code below.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ChildGetter : MonoBehaviour
{
private List<DepthLevelHandler> _allChildren = new List<DepthLevelHandler>();
private List<DepthLevelHandler> _allChildrenAlternative = new List<DepthLevelHandler>();
private DepthLevelHandler _deepest;
private GameObject _mostBottomDeepest;
private DepthLevelHandler _deepestMostBottom;
private IEnumerator GetDeepestChild(Action callBack = null)
{
for (int i = 0; i < transform.childCount; i++)
{
DepthLevelHandler dLH = new DepthLevelHandler
{
depthLevel = 1,
gameObject = transform.GetChild(i).gameObject
};
_allChildren.Add(dLH);
}
_allChildrenAlternative = _allChildren;
for (int i = 0; i < transform.childCount; i++)
{
StartCoroutine(AddAllChildrenToList(_allChildren[i]));
yield return new WaitForSeconds(1f);
}
_deepest = _allChildren[0];
foreach (var child in _allChildren)
{
if (child.depthLevel > _deepest.depthLevel)
{
_deepest = child;
}
}
Debug.Log("Name of deepest child : "+_deepest.gameObject.name);
callBack?.Invoke();
}
private IEnumerator AddAllChildrenToList(DepthLevelHandler parent)
{
if (parent.gameObject.transform.childCount == 0) yield break;
for (int i = 0; i < parent.gameObject.transform.childCount; i++)
{
GameObject newChild = parent.gameObject.transform.GetChild(i).gameObject;
int newDepthLevel = parent.depthLevel + 1;
DepthLevelHandler newDepthHandler = new DepthLevelHandler
{
depthLevel = newDepthLevel,
gameObject = newChild
};
if (!_allChildrenAlternative.Contains(newDepthHandler))
{
_allChildrenAlternative.Add(newDepthHandler);
if (newDepthHandler.gameObject.transform.childCount != 0)
{
yield return new WaitForSeconds(0.01f);
yield return AddAllChildrenToList(newDepthHandler);
}
}
}
}
private void GetDeepestMostBottomChild()
{
List<DepthLevelHandler> allChildrenWithSameDepthLevel = new List<DepthLevelHandler>();
allChildrenWithSameDepthLevel.Add(_deepest);
_deepestMostBottom = _deepest;
foreach (var child in _allChildrenAlternative)
{
if (child.depthLevel == _deepest.depthLevel)
{
allChildrenWithSameDepthLevel.Add(child);
}
}
foreach (var child in allChildrenWithSameDepthLevel)
{
if (child.gameObject.transform.GetSiblingIndex() > _deepestMostBottom.gameObject.transform.GetSiblingIndex())
{
_deepestMostBottom = child;
}
}
Debug.Log("name of deepest most bottom child : "+_deepestMostBottom.gameObject.name);
}
private IEnumerator GetMostBottomDeepestChild()
{
Transform mostBottom = transform;
while (mostBottom.childCount != 0)
{
yield return new WaitForSeconds(0.02f);
mostBottom = mostBottom.GetChild(mostBottom.childCount - 1);
}
_mostBottomDeepest = mostBottom.gameObject;
Debug.Log("name of most bottom deepest child : "+_mostBottomDeepest.gameObject.name);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.A)) StartCoroutine(GetDeepestChild(GetDeepestMostBottomChild));
if (Input.GetKeyDown(KeyCode.B)) StartCoroutine(GetDeepestChild());
if (Input.GetKeyDown(KeyCode.C)) StartCoroutine(GetMostBottomDeepestChild());
}
}
public class DepthLevelHandler
{
public int depthLevel = 0;
public GameObject gameObject = null;
}
Upvotes: 0
Reputation: 467
I recently had this issue, where I was making a Klondike solitaire game with stacks of cards. I knew that they would all only have 1 child and I wanted to grab the bottom most child of 1 column and move that child to another column. Unfortunately, all of the other answers here simply speculate on if this should be done rather than providing a method to solve the problem. So, I created a method to grab children. Please note that this will work best when used with a stack of single children.
/**
* returns parent if there are no children
*/
private GameObject GetLastChild(GameObject parent)
{
//the parent object
GameObject lastChild = parent;
/*
Initialize a checkChild element
while check child is not null, continue checking
assign the checkChild to its child
*/
for (GameObject checkChild = parent; checkChild != null; checkChild = checkChild.transform.GetChild(0).gameObject)
{
lastChild = checkChild;
if (checkChild.transform.childCount == 0)
{
break;
}
}
return lastChild;
}
Upvotes: 0
Reputation: 1042
If you want the child object itself rather than only the transform:
int lastChildIndex = parentObject.transform.childCount - 1;
lastChildObject = parentObject.transform.GetChild(lastChildIndex).gameObject;
Upvotes: 0
Reputation: 7824
Create a list of all the children under the parent's transform.
List<GameObject> list = new List<GameObject>();
foreach(Transform t in transform)
{
list.Add(t.gameObject);
if(t.childCount > 0)
foreach(Transform c in t)
list.Add(c);
}
The last element is the last child:
GameObject lastChild = list[list.Count-1];
Upvotes: -2
Reputation: 33
First you would need to define what is the bottom child, since the depth of the children can depend also on the siblings.
for example:
But then each of the children can have their own children
So in this case al of the childrens' children are at the same level.
Maybe you are refering to the bottom most as seen in the editor? In that case maybe add something to the nae in order to search for it...
Upvotes: 0