Search Unity

How can I add a component to thousands of objects of the same name or tag?

Discussion in 'Editor & General Support' started by Just_ABoy, Jul 27, 2020.

  1. Just_ABoy

    Just_ABoy

    Joined:
    Jul 3, 2020
    Posts:
    5
    I need some optimization in my 2D project, it is a wide openworld with thousands of objects in it, now I am trying to disable them using OnBecameVisible and OnBecameInvisible, but I found out that it only works when I have a Renderer.
    In this case I have this situation:
    upload_2020-7-27_12-23-31.png

    So I would like to either add a renderer to the object 'Spikes' or add a script to 'spikeson' so that i can check if it is on screen.
    The problem is that there are a lot of objects like this in the scene, so is there a way to edit them all at once using the editor instead of adding the component at runtime in the start method?

    Using Unity 5.6.4p2
     
    Last edited: Jul 27, 2020
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,911
    Search for 'Spikes' in the hierarchy window, then just select them all and add the component?

    But I'm confused. If they don't have renderers already how are they visible in the first place?
     
    Joe-Censored likes this.
  3. hotcarl

    hotcarl

    Joined:
    Aug 21, 2017
    Posts:
    18
    If you want to select a bunch of objects that happen to share similar names, as the person above me said, search for it in the Hierarchy tab. There is a search box at the very top of that window, just right of the plus sign. (I'm on a Mac, apologies if this is different on your computer) If that limits the objects in your Hierarchy tab to what you're looking for, then select add, and add component.

    Now... as far as the optimization goes, I've done a similar thing, but using a different method. I'll explain that in case it is of benefit. I develop in a 3D environment, but the logic should be easy enough to convert to2D. First thing I do is tag all of the objects I toggle on/off. Optionally you could create a List or Array to track them. I then do a foreach loop and search for that tag. For each result, I compare the distance to player based on Vector3.Distance() result. Then toggle their gameObject on/off. It looks something like this (code NOT tested):

    NOTE: I don't run this every update. I usually run it every X number of seconds.

    foreach (GameObject gmObj in listOfToggleObjects) // Method 1
    // foreach (GameObject gmObjt in GameObject.FindObjectsWithTag("Toggle") // Method 2
    {
    float distanceApart = Vector3.Distance(player.transform.position, gmObj.transform.position);
    if ( distanceApart > 50 )
    {
    gmObj.SetActive(false);
    }
    else
    {
    gmObjet.SetActive(true);
    }
    }

    If you really want to get frisky, you could use this type of logic to swap out high and low res meshes. I've done that before, it's pretty neat. Trick is to get the high and low res meshes to line up well.

    Good luck.
     
  4. Just_ABoy

    Just_ABoy

    Joined:
    Jul 3, 2020
    Posts:
    5
    Thank you @hotcarl I will also try out your method! However thank you all for the tips!
     
  5. Just_ABoy

    Just_ABoy

    Joined:
    Jul 3, 2020
    Posts:
    5
    Sorry @hotcarl but I cannot figure out how I can reactivate the game objects when they are near enough, there is no unity function that returns me disabled objects and they are destroyed when disabled, maybe I can just disable their logic with a boolean and turn off their animator?
     
  6. fffMalzbier

    fffMalzbier

    Joined:
    Jun 14, 2011
    Posts:
    3,276
    Take a look at the CullingGroup API

    https://docs.unity3d.com/Manual/CullingGroupAPI.html

    from the examples
    I used it very nicely on IOS to have objects that are invisible by the shader be culled even if they are on screen as long they have a specific distance to the reveling effect center.
     
    hotcarl likes this.
  7. hotcarl

    hotcarl

    Joined:
    Aug 21, 2017
    Posts:
    18
    Yeah, that's a frustrating problem I'm too familiar with. Fortunately there are a couple options I have discovered.
    1. I noticed that inactive objects can be found if they're stored in a List or Array. For my memory script, I have the items all start out active, and "announce" themselves to my memory manager script. Something like this:
    Code (CSharp):
    1. GameObject.Find("GameManager").GetComponent<MemoryManager>().AnnounceSelf(gameObject);
    2. The other option is to use the Transform.Find() method. That only works if you know where the inactive gameObject is located. The Transform.Find() method only searches for children of a parent Transform.

    So for instance, if you're Heirarchy has an inactive gameObject named Tree like this:
    /Trees/Tree
    You could do something like this:
    Code (CSharp):
    1. GameObject inactiiveGameObject = GameObject.Find("Trees").transform.Find("Tree").gameObject;
    2. inactiveGameObject.SetActive(true);
    3.  
    Good Luck!
     
  8. hotcarl

    hotcarl

    Joined:
    Aug 21, 2017
    Posts:
    18
    Wow! Thank you for posting that. I had no idea. I am going to give it a go. *thumbs up emote goes here*