A detailed explanation of how Unity gets objects in the scene, and how to get the root node whose active is false

The following test scenario is used as an example to illustrate. The script tested at this time is mounted on TestNode1

一、GameObject.Find(string param)

Find by name

The most common method is GameObject.Find, where the parameter can be filled with the name of the object , and it is a global search, which has nothing to do with the node where the script is located. For example, directly search TestNode111 and TestNode22 below, you can find the corresponding point

            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");
            }

However, since this method searches for global objects, it will consume a lot of performance when there are many objects, so don't call it too frequently. Another thing to note is if there is a node with the same name in the scene. Only the first node found will be returned here, so avoid duplicate names.

Also, when the GameObject.Find parameter is the object name, the node whose active is false cannot be found . You can try to set the active of TestNode111 to false. You can see that this node cannot be found at this time.

Find by path

The parameter can also fill in the path . The path here can be an absolute path or a relative path . The cost of finding a node through the path will be lower than directly based on the object name. The node structure is still as follows

The absolute path starts with "/" or the object name, and the scene name is not in this path. For example, find the point TestNode111 .

The absolute path should be filled with GameObject.Find( "/TestNode1/TestNode11/TestNode111" )

If you fill in GameObject.Find("/TestScene/TestNode1/TestNode11/TestNode111") or GameObject.Find("TestScene/TestNode1/TestNode11/TestNode111"), the corresponding node cannot be found.

Relative paths need to start with the name of the object, not "/"

For example, GameObject.Find("TestNode11/TestNode111") finds success

And GameObject.Find("/TestNode111") failed to find

            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");
            }

When using the absolute path to find the active value of false, if the active node of the searched node is false and the parent node active is true, the node can still be found . The result is as follows

 

 If you use relative path search, you cannot find the node whose active is false

And when his parent node active is also false, the search will fail, and the results are as follows

 

二、GameObject.FindWithTag

The logic of GameObject.FindWithTag is basically the same as GameObject.Find, which is also a global search. Similar to GameObject's search function by name, except that the search is based on the Tag attribute, and it is also impossible to find nodes whose active is false.

 三.Transform.Find

transform.Find is to find the child node of the mount script node, and only the child node can be found, and the direct Find grandchild cannot be found . If you want to find the grandchild node, you need to call the Find function step by step. And transform.Find can also find nodes whose active is false . The following is the result of directly finding child nodes and grandchild nodes

            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");
            }

 Fourth, the method of obtaining the root node whose active is false

Because transform can find nodes whose active is false through the hierarchical relationship. So using transform.Find can basically find all the nodes in the scene. For the root node that is not on the node tree of this Transfrom, such as TestNode2 in the example, if active is true, you can also use GameObject.Find to find it directly.

But there is also a special case, that is, the root node whose active is false is not on the same node tree, and TestNode2 in the following figure is the root node whose active is false.

There are two ways

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

Resources.FindObjectsOfTypeAll(typeof(GameObject))

code show as below

            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;
                    }

                }
            }

You can see the results below, both methods can successfully find TestNode2

 

Guess you like

Origin blog.csdn.net/shaobing32/article/details/122977889
Recommended