繁体   English   中英

查找游戏对象的孩子的孩子

[英]Find children of children of a gameObject

我在场景中有一个预制件,我想访问该预制件的子代,该预制件的结构是这样的:

PauseMenu
    UI_Resume
        TextField
        TextField2
            UI_Side_Back  <---- (I need this child)
    UI_Home

transform.FindChild只返回第一级子和loop在变换循环中第一级子太:

foreach (Transform item in PooledPause.transform) {
        Debug.Log(item.name);
}

我认为它需要是一种递归方法或其他东西。 我怎样才能找到那个孩子?

您可以使用路径来查找转换:

 var target = transform.Find("UI_Resume/TextField2/UI_Side_Back");

Transform.Find文档中

如果名称包含“/”字符,它将像路径名称一样遍历层次结构。

上面的“RecursiveChildFind”不起作用,因为它只会搜索一个孩子,而不是所有孩子。 一个工作版本如下:

Transform RecursiveFindChild(Transform parent, string childName)
{
    foreach (Transform child in parent)
    {
        if(child.name == childName)
        {
            return child;
        }
        else
        {
            Transform found = RecursiveFindChild(child, childName);
            if (found != null)
            {
                    return found;
            }
        }
    }
    return null;
}

我尝试了所有解决方案,但没有一个对我有用。 使用 Unity Find不起作用,因为我不知道我孩子的父母的姓名。 这里的递归解决方案仅适用于只有一个孩子的父母,这也不是我的情况。 因此,我创建了以下通用递归查找器,可在任何类型的GameObject层次结构(或树)中工作。

public static Transform RecursiveFindChild(Transform parent, string childName)
{
    Transform child = null;
    for (int i = 0; i < parent.childCount; i++)
    {
        child = parent.GetChild(i);
        if (child.name == childName)
        {
            break;
        }
        else
        {
            child = RecursiveFindChild(child, childName);
            if (child != null)
            {
                break;
            }
        }
    }

    return child;
}

注意:小心使用,避免大的GameObject树。

我以前不为 Unity3D 开发,但我建议您为您的对象设置一个标签并通过标签搜索它。 这样

  public static T FindComponentInChildWithTag<T>(this GameObject parent, string tag)where T:Component{
       Transform t = parent.transform;
       foreach(Transform tr in t)
       {
              if(tr.tag == tag)
              {
                   return tr.GetComponent<T>();
              }
              else
              {
                   tr.GetComponent<T>().FindComponentInChildWithTag(tag);
              }
       }
  }

或者像这样

但是,如果您真的想按名称搜索,则可以将之前的代码更改为如下所示

if(tr.name == "object name")

或者像这样执行 find() :

tr.Find("Bone");

//or

parent.Find("UI_Resume/TextField2/UI_Side_Back");

试试这个递归方法。

public static Transform RecursiveFindChild(Transform parent, string childName)
{
    Transform result = null;

    foreach (Transform child in parent)
    {
        if (child.name == childName)
            result = child.transform;
        else
            result = RecursiveFindChild(child, childName);

        if (result != null) break;
    }

    return result;
}

如果您不知道父级的名称可能是什么,实现此目的的一种方法是使用:

Transform GetChildWithName(GameObject go, string childName)
{
    Transform child = null;
    foreach (Transform t in go.GetComponentsInChildren<Transform>())
    {
        if (t.name == childName)
        {
            child = t;
            break;
        }
    }
    return child;
}

感谢Dan Puzey的回答,另外,如果你想在你的对象上使用递归循环,你可以像这样实现:

void Start()
{
    GameObject theChild = RecursiveFindChild (theParentGameObject.transform, "The Child Name You Want");
}

GameObject RecursiveFindChild(Transform parent, string childName)
{
    foreach (Transform child in parent) {
        if(child.name == childName)
            return child.gameObject;
        else 
            return RecursiveFindChild(child, childName);
    }

    return null;
}

这是另一种解决方案,可让您根据任何标准查找任何深度的儿童 它使用深度优先的方法。 因此,我建议将感兴趣的对象尽可能高地放置在树上以节省一些操作。

它是这样使用的: parent.FindRecursive("child");

或者,如果您需要更多灵活性: parent.FindRecursive(child => child.GetComponent<SpriteRenderer>() != null && child.name.Contains("!"));

using System;
using UnityEngine;

public static class TransformExtensions
{
    public static Transform FindRecursive(this Transform self, string exactName) => self.FindRecursive(child => child.name == exactName);

    public static Transform FindRecursive(this Transform self, Func<Transform, bool> selector)
    {
        foreach (Transform child in self)
        {
            if (selector(child))
            {
                return child;
            }

            var finding = child.FindRecursive(selector);

            if (finding != null)
            {
                return finding;
            }
        }

        return null;
    }
}

也可以扔在我的版本中。 如何按名称查找 Child Child。

不更新循环友好。

public GameObject FindChildGameObjectByName(GameObject go, string gameObjectName)
{
    GameObject retrunGO = null;

    for (int i = 0; i < go.transform.childCount; i++)
    {
        if (go.transform.GetChild(i).name == gameObjectName)
        {
            retrunGO = go.transform.GetChild(i).gameObject;
        }

        GameObject tmp = FindChildGameObjectByName(go.transform.GetChild(i).gameObject, gameObjectName);

        retrunGO = (tmp != null ? tmp : retrunGO);
    }

    return retrunGO;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM