Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way to find Gameobjects without GameObject.Find

Using Unity, I'm working on a game where all Gameobjects with a certain tag vanish/reappear fairly regularly (every 10 seconds on average). I use GameObject.FindGameObjectsWithTag() to create a Gameobject[] through which I enumerate every time that the objects need to be made visible/invisible. I cannot call it once, on Start, as new Gameobjects are created while playing. I thought that it would be worse to access and change the Gameobject[] every time something got created/destroyed. Is there a better way to handle this. I know how bad of an impact on performance the GameObject.Find methods make...

like image 665
Rupture Avatar asked Dec 23 '22 08:12

Rupture


2 Answers

Yes, there is a better way to do this. Have a script with List variable that can store GameObjects. Making it a singleton is better but not necessary.

This singleton script should be attached to an empty GameObject:

public class GameObjectManager : MonoBehaviour
{
    //Holds instance of GameObjectManager
    public static GameObjectManager instance = null;
    public List<GameObject> allObjects = new List<GameObject>();

    void Awake()
    {
        //If this script does not exit already, use this current instance
        if (instance == null)
            instance = this;

        //If this script already exit, DESTROY this current instance
        else if (instance != this)
            Destroy(gameObject);
    }
}

Now, write a script that registers itself to the List in the GameObjectManager script. It should register itself in the Awake function and un-register itself in the OnDestroy function.

This script must be attached to each prefab you want to add to the List. Simply do that from the Editor:

public class GameObjectAutoAdd : MonoBehaviour
{
    void Awake()
    {
        //Add this GameObject to List when it is created
        GameObjectManager.instance.allObjects.Add(gameObject);
    }

    void OnDestroy()
    {
        //Remove this GameObject from the List when it is about to be destroyed
        GameObjectManager.instance.allObjects.Remove(gameObject);
    }
}

If the GameObjects are not prefabs but GameObjects created through code, simply attach the GameObjectAutoAdd script to them once they are created:

GameObject obj = new GameObject("Player");
obj.AddComponent<GameObjectAutoAdd>();

You can now access your GameObjects in the List with GameObjectManager.instance.allObjects[n]; where n is the index number and you don't have to use any of the Find functions to find the GameObject anymore.

like image 142
Programmer Avatar answered Dec 26 '22 11:12

Programmer


It's true that calling to GameObject.Find consumes a lot of recourses.

The point should be to save the result and use it always but I understand that you can't do that.

Other option is to have all this gameobjects as a child of one gameobject let's call it handlerGameobject. It will have a script that doesn't use GameObeject.Find it could getChild or transform.Find that uses less resources.

Hope it helps!

like image 23
Chopi Avatar answered Dec 26 '22 10:12

Chopi