Unity获取场景中物体的方法详解,以及如何获取active为false的根节点

下面以如下的测试场景作为例子,进行说明。此时测试的脚本是挂载在TestNode1

一、GameObject.Find(string param)

根据名字查找

最常用的方法是GameObject.Find,这里参数可以填物体的名字,并且是全局搜索,与脚本所在的节点并没有关系,比如下面直接查找TestNode111和TestNode22,均可以找到对应的点

            if (GameObject.Find("TestNode111") != null)
            {
                Debug.Log("GameObject.Find TestNode111 true");
            }
            else
            {
                Debug.Log("GameObject.Find TestNode111 false");
            }


            if (GameObject.Find("TestNode22") != null)
            {
                Debug.Log("GameObject.Find TestNode22 true");
            }
            else
            {
                Debug.Log("GameObject.Find TestNode22 false");
            }

但是由于这个方法查找的是全局的物体,所以当物体比较多的时候会消耗较大的性能,所以不要过于频繁地调用。还有要注意的一点是,如果场景中存在同名节点的话。这里只会返回找到的第一个节点,所以要避免重名的情况。

还有就是GameObject.Find参数为物体名时,无法找到active为false的节点,可以尝试将TestNode111的active设为false,可以看到这时候就无法找到这个节点了

根据路径查找

参数还可以填路径,这里的路径可以是绝对路径相对路径,通过路径来寻找节点的消耗,会比直接根据物体名称要低,节点结构还是如下

绝对路径是以"/"开头或者物体名字开头,并且场景名称是不在这个路径里面。比如查找TestNode111这个点。

绝对路径应该填GameObject.Find("/TestNode1/TestNode11/TestNode111")

如果填的是GameObject.Find("/TestScene/TestNode1/TestNode11/TestNode111")或者GameObject.Find("TestScene/TestNode1/TestNode11/TestNode111")都是无法查找到对应节点的。

相对路径的时候需要以物体的name开头,而不能以"/"开头

比如GameObject.Find("TestNode11/TestNode111") 查找成功

而GameObject.Find("/TestNode111")查找失败

            if (GameObject.Find("TestNode11/TestNode111") != null)
            {
                Debug.Log("GameObject.Find TestNode11/TestNode111 true");
            }
            else
            {
                Debug.Log("GameObject.Find TestNode11/TestNode111 false");
            }

            if (GameObject.Find("/TestNode1/TestNode11/TestNode111") != null)
            {
                Debug.Log("GameObject.Find /TestNode1/TestNode11/TestNode111 true");
            }
            else
            {
                Debug.Log("GameObject.Find /TestNode1/TestNode11/TestNode111 false");
            }

            if (GameObject.Find("TestNode1/TestNode11/TestNode111") != null)
            {
                Debug.Log("GameObject.Find TestNode1/TestNode11/TestNode111 true");
            }
            else
            {
                Debug.Log("GameObject.Find TestNode1/TestNode11/TestNode111 false");
            }


            if (GameObject.Find("TestScene/TestNode1/TestNode11/TestNode111") != null)
            {
                Debug.Log("GameObject.Find TestScene/TestNode1/TestNode11/TestNode111 true");
            }
            else
            {
                Debug.Log("GameObject.Find TestScene/TestNode1/TestNode11/TestNode111 false");
            }

            if (GameObject.Find("/TestNode111") != null)
            {
                Debug.Log("GameObject.Find /TestNode111 true");
            }
            else
            {
                Debug.Log("GameObject.Find /TestNode111 false");
            }

用绝对路径找active为false的时候,如果被查找的节点active为false,而父节点active为true,还是可以找到这个节点的。结果如下

 

 用相对路径查找,则无法找到active为false的节点

而当他的父节点active也为false的时候查找就会失败,结果如下

 

二、GameObject.FindWithTag

GameObject.FindWithTag的逻辑跟GameObject.Find基本相同,同样是全局查找。跟GameObject根据名字查找的功能类似,只不过查找的是根据Tag属性,而且同样无法找到active为false的节点。

 三.Transform.Find

transform.Find是查找挂载脚本节点的子节点,并且只能找到孩子节点,直接Find孙子是无法找到的。如果想要找到孙子节点,就需要逐级地去调用Find函数。并且transform.Find也可以找到active为false的节点,下面是直接查找孩子节点和孙子节点的结果

            if (this.transform.Find("TestNode11") != null)
            {
                Debug.Log("this.transform.Find TestNode11 true");
            }
            else
            {
                Debug.Log("this.transform.Find TestNode11 false");
            }


            if (this.transform.Find("TestNode111") != null)
            {
                Debug.Log("this.transform.Find TestNode111 true");
            }
            else
            {
                Debug.Log("this.transform.Find TestNode111 false");
            }

 四、获取active为false的根节点的方法

因为transform可以通过层级关系查找active为false的节点。所以用transform.Find基本可以找到场景里的所有节点。对于不在这个Transfrom的节点树上的根节点,比如例子中的TestNode2,如果active为true,也可以直接用GameObject.Find来查找。

但是这里面还包含一种特殊的情况,就是不在同一个节点树上,active为false的根节点,下图中的TestNode2是active为false的根节点。

这时候有两种方法

UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects()

Resources.FindObjectsOfTypeAll(typeof(GameObject))

代码如下

            GameObject[] allRoot = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
            for (int i = 0; i < allRoot.Length; i++)
            {
                if (allRoot[i].name == "TestNode2")
                {
                    Debug.Log("GetRootGameObjects find TestNode2 true");
                    break;
                }
            }


            GameObject[] all = Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[];
            for (int i = 0; i < all.Length; i++)
            {
                var item = all[i];
                if (item.scene.isLoaded)
                {
                    if (item.name == "TestNode2")
                    {
                        Debug.Log("FindObjectsOfTypeAll find TestNode2 true");
                        break;
                    }

                }
            }

可以看到下方的结果,两种方法都可以顺利到找到TestNode2

 

猜你喜欢

转载自blog.csdn.net/shaobing32/article/details/122977889