edward au
edward au

Reputation: 31

Get bottom most child

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

Answers (6)

Abolfazl
Abolfazl

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

Display name
Display name

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

Onat Korucu
Onat Korucu

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

Flyingmartini
Flyingmartini

Reputation: 149

lastChild = transform.GetChild(transform.childCount - 1);

Upvotes: 14

axwcode
axwcode

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

Caribenz
Caribenz

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:

  • Root
    • child_1
    • child_2
    • child_3

But then each of the children can have their own children

  • Child_1
    • Child_1A
    • Child_1B
  • Child_2
    • Child_2A
    • Child_2B
    • Child_2C
    • Child_2D
    • Child_2E

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

Related Questions