Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Destroy/Purge GameObjects in Parent Empty Object

Discussion in 'Scripting' started by aolba, Jul 27, 2018.

  1. aolba

    aolba

    Joined:
    Nov 27, 2014
    Posts:
    7
    Part of my Class code manage to create a GameObject, attach a SpriteRenderer and finally set all this as a child of the main Parent. This will be run for 400 or 500 times. So I don't want to have that much of items in my editor. I have the idea of remove all those dynamic GameObjects at some point, but I get some errors or the destroy order is just ignored. I try with OnApplicationQuit and OnDIsable. I see some idea of store the GameObjects in an array and read that array for the destruction process, but then I see this comment "... you should never iterate through arrays and destroy the elements you are iterating over..." So I run out of ideas.
     
  2. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    If it is all children you want to destroy, then you could try something like this (but don't, instead see the edited code):
    Code (CSharp):
    1.         //while(transform.childCount > 0)
    2.         //    Destroy(transform.GetChild(0).gameObject);
    Edit: scratch that it doesn't work because the objects aren't immediately removed. Ho hum.
    This seems to work ok, though :-
    Code (CSharp):
    1.         foreach (Transform child in transform)
    2.             Destroy(child.gameObject);
     
    Last edited: Jul 28, 2018
    aolba likes this.
  3. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    As for your question about destroying elements of an array you are iterating over, that is because it may cause you to skip elements of the array as its length and index numbers of elements are changing while looping through it.

    Calling Destroy on a GameObject doesn't destroy it immediately though (unless calling DestroyImmediate) so you should be fine looping through an array and destroying all of its GameObjects.

    You can also make a shallow copy of the array and iterate over that instead, or build as a list but iterate over the list by converting it to an array, which is basically a shallow copy of the list as an array.

    List to array iteration example:
    Code (csharp):
    1. List<string> stringList = new List<string>();
    2.  
    3. stringList.Add("CNN");
    4. stringList.Add("BBC");
    5. stringList.Add("Fox");
    6. stringList.Add("Guardian");
    7. stringList.Add("ABC");
    8. stringList.Add("NBC");
    9.  
    10. foreach (string newsOutlet in stringList.ToArray())
    11. {
    12.     if (newsOutlet.Length < 4)
    13.     {
    14.         stringList.Remove(newsOutlet);
    15.     }
    16. }
    The above code will remove all the strings except "Guardian" from the list without issue, since it is actually iterating over an array copy of the list rather than the list which is being modified.
     
    Last edited: Jul 27, 2018
  4. aolba

    aolba

    Joined:
    Nov 27, 2014
    Posts:
    7
    Thanks Doug_B, I give a try with the code, but is as usuall. Destroy action is ignored ( no errors )
    I place the code in the Parent ( so he clean himself ) I try to insert the code in
    OnApplicationQuit and OnDisable. Same result.
     
  5. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Objects aren't destroyed immediately, so that looks like an infinitely loop just getting the same child over and over from where I'm sitting.
     
    aolba likes this.
  6. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Just be sure to take note of my edit (as the original code causes an infinite loop o_O). But the
    foreach
    works ok. Maybe try putting a breakpoint on the
    foreach
    if you do try it. Then see if the line is reached and step it in the debugger to see that it iterates through all the children. They should then be destroyed the following frame.

    Hi Joe-Censored, you are indeed correct. I left the code in place (not sure what the etiquette is with removing comments on these forums) but I added an Edit in the comment with a working piece of code instead.
     
    aolba likes this.
  7. aolba

    aolba

    Joined:
    Nov 27, 2014
    Posts:
    7
    Thanks for all the help Doug_B and joe-censored. I manage to make it work. The work flow is kind of new for me in unity and I probably miss something. After Debug, debug, debug and debug more, I noted a few things:
    1. The class that handle the dynamic GO creation-attach was triggering his Start() twice.
    2. The Destroy part was actually doing "something" because visually the GameObject was still attached to the parent in the editor, but any code reference after the Destroy seems like it works.
    I think part of my problem was that the creator-attach class was inserted on stage by drag and attach it to an empty GameObject. All start to work fine when I insert this class by code.

    At the end The logic for Destroy was correct and I end placing that part of the code here OnDisable.
     
  8. aolba

    aolba

    Joined:
    Nov 27, 2014
    Posts:
    7
    using gameObject.AddComponent I think I even doesn't have to worry about destroy the GameObjects with code. They are removed from editor automatically. I could take care of the destroy part in another animation class, but that's for other moment.