如何通过脚本查找 GameObject 的子对象或附加到子 GameObject 的脚本

Posted

技术标签:

【中文标题】如何通过脚本查找 GameObject 的子对象或附加到子 GameObject 的脚本【英文标题】:How to find child of a GameObject or the script attached to child GameObject via script 【发布时间】:2017-04-06 17:33:51 【问题描述】:

我知道这是一个有点愚蠢的问题,但是我将如何通过脚本引用游戏对象的子对象(立方体)(脚本附加到游戏对象)。 (相当于GetComponent之类的东西)

【问题讨论】:

【参考方案1】:

按索引查找子游戏对象

您可以使用GetChild 函数获取游戏对象的第一个子对象。

GameObject originalGameObject = GameObject.Find("MainObj");
GameObject child = originalGameObject.transform.GetChild(0).gameObject;

您可以通过将子游戏对象的索引号(例如 1、2、3)提供给GetChild 函数来获取其他子对象。

如果它是原始游戏对象中的孩子的孩子?我会不会 必须重复它,否则它只是第n个吗

你先找到孩子,然后从引用中找到那个孩子的孩子。

假设这是 OriginalGameObject/Prefab 层次结构:

原始游戏对象 孩子1 孩子2 孩子3 childOfChild3

如您所见,OriginalGameObjectchild1child2child3 的父级。 childOfChild3 是child3 的孩子。

假设你想访问childs,而你只需要引用OriginalGameObject,它是父游戏对象:

//Instantiate Prefab
GameObject originalGameObject  = Instantiate(prefab);

//To find `child1` which is the first index(0)
GameObject child1 = originalGameObject.transform.GetChild(0).gameObject;

//To find `child2` which is the second index(1)
GameObject child2 = originalGameObject.transform.GetChild(1).gameObject;

//To find `child3` which is the third index(2)
GameObject child3 = originalGameObject.transform.GetChild(2).gameObject;

索引从0开始,所以真正的索引号是index-1,就像数组一样。

现在,要获取 childOfChild3 的引用,它是 child3 的子代,但您只有 OriginalGameObject 的引用,它是父 GameObject:

首先,获取child3 的引用,然后从中获取childOfChild3

GameObject mychild = originalGameObject.transform.GetChild(2).gameObject;
GameObject childOfChild3 = mychild.transform.GetChild(0).gameObject;

使用循环按索引查找 [all] 子游戏对象

循环遍历 originalGameObject 的所有子对象:

GameObject originalGameObject = Instantiate(prefab);
for (int i = 0; i < originalGameObject.transform.childCount; i++)

    GameObject child = originalGameObject.transform.GetChild(i).gameObject;
    //Do something with child

您还可以使用transform.FindChild 函数按名称查找孩子。我不建议您这样做。当多个孩子共享相同的名字时,它似乎很慢并且会发生冲突。这就是你使用GetChild的原因。

按名称查找子游戏对象

GameObject child1 = originalGameObject.transform.FindChild("child1").gameObject;
GameObject child2 = originalGameObject.transform.FindChild("child2").gameObject;
GameObject child3 = originalGameObject.transform.FindChild("child3").gameObject;

要查找childOfChild3,您可以使用“/”轻松完成,就像使用文件目录一样。您提供 parent/child 然后名称。 childOfChild3 的父级是 child3。所以,我们在 FindChild 函数中使用 childOfChild3/child3

GameObject childOfChild3 = originalGameObject.transform.FindChild("child3/childOfChild3").gameObject;

查找附加到子游戏对象的脚本/组件

如果你想要的只是附加到子游戏对象的脚本,那么使用GetComponentInChildren

MyScript childScript = originalGameObject.GetComponentInChildren<MyScript>();

如果有多个孩子使用相同的脚本,而您只想获得所有附加到他们的脚本,则使用GetComponentsInChildren

MyScript[] childScripts = originalGameObject.GetComponentsInChildren<MyScript>();
for (int i = 0; i < childScripts.Length; i++)

    MyScript myChildScript = childScripts[i];
    //Do something with myChildScript

【讨论】:

程序员,只有第一个?? 检查更新。你说的是孩子不是孩子,所以我假设只有一个孩子。 Knetic 提供的答案/代码甚至不应该在 Unity 5 上编译。 如果它是原始游戏对象中孩子的孩子?我是否只需要重复它还是只是第n个呢 其实等等,有办法吗? 等一下。我正在编辑我的答案来回答这个问题。【参考方案2】:

gameObject.transform.children 包含给定游戏对象的所有直接子级。您可以遍历它并找到所需的孩子。例如,按名称;

for(int i = 0; i < gameObject.transform.childCount;)

    if(gameObject.transform.children[i].name == "someName")
    
        // do what you need with it
    


有几种迭代方法。您可以使用枚举,如these docs 中所示,或使用FindChild。

如果您有一些其他条件,例如想要找到具有特定类型组件的子项,而不仅仅是按名称,通常您会想要遍历子项。

【讨论】:

非常感谢,我可以在 11 分钟内先接受这个答案,但别担心,我会... 只是一件事,你确定没有更简单的方法 我刚刚更新了一些按名称查找的便捷方法,以及一些关于何时需要迭代子项与使用 FindChild 的说明【参考方案3】:

我发现这个非常短的方法只有 2 行, 我的播放器层次结构是这样的:

-播放器

    头 子弹位置

代码:

Transform[] ObjectChildrens;
ObjectChildrens = gameObject.GetComponentsInChildren<Transform>();
GameObject Head = System.Array.Find(ObjectChildrens, p => p.gameObject.name == "Head").gameObject;


GameObject BulletPos = System.Array.Find(ObjectChildrens, p => p.gameObject.name == "BulletPos").gameObject;
GameObject LifeProgresBar = System.Array.Find(ObjectChildrens, p => p.gameObject.name == "LifeProgresBar").gameObject.GetComponent<Text>().text = "100";
CapsuleCollider2D cc = System.Array.Find(ObjectChildrens, p => p.gameObject.name == "HeadPlace").gameObject.GetComponent<CapsuleCollider2D>();

【讨论】:

【参考方案4】:

你可以在父游戏对象中有公共变量。

public Tranform childGameObject;

然后将您的子游戏对象分配给它。

这样可以避免隐藏的依赖关系。以及您的子立方体可以在另一个父级和另一个父级内部。

【讨论】:

gabs,这不起作用,因为正在实例化游戏对象,我需要对该实例的子对象的引用

以上是关于如何通过脚本查找 GameObject 的子对象或附加到子 GameObject 的脚本的主要内容,如果未能解决你的问题,请参考以下文章

Unity Editor 脚本用指定 GameObject 的子级填充序列化数组 [关闭]

如何查找场景中所有的物体啊,包括在Hierarchy中不显示的物体

Unity Gameobject Transform

unity3d中给GameObject绑定脚本的代码

将 GameObject Unity 导出为 .fbx 或 .obj

unity基础(GameObject transform)