Search Unity

Question Remove destroyed object inside collider from a list?

Discussion in 'Scripting' started by skyLark9, Oct 18, 2020.

  1. skyLark9

    skyLark9

    Joined:
    May 2, 2018
    Posts:
    135
    I have object when enter inside a collider. script add it into a list and when it goes out it does removed it. But if I destroy it inside the collider it doesn't remove from the list only showing (Missing GameObject). I need when I destroy it inside collider it should remove from the list.

    public List<GameObject> Sweets;

    void OnTriggerEnter2D(Collider2D other)
    {
    if (other.transform.name == ("gem"))
    {
    Sweets.Add(other.transform.gameObject);
    }
    }

    void OnTriggerExit2D(Collider2D other2)
    {
    if (other2.transform.name == ("gem"))
    {
    Sweets.Remove(other2.transform.gameObject);
    }
    }
    [/code]
     
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    1st
    there is too little information in your example.
    I can only say that you're assuming that this should work without checking what is really going on.
    you either have a serious error somewhere else, or this doesn't work for some (to me unknowable) reason.
    your problem has nothing to do with the list btw.

    why don't you try to place
    Code (csharp):
    1. Debug.Log("Add " + other.transform.name); // this is what names are for, see 2nd below
    instead of Sweets.Add(...)

    and
    Code (csharp):
    1. Debug.Log("Remove " + other2.transform.name); // does it matter if its other or other2?
    2. // I'm not sure if you understand how variables work
    instead of Sweets.Remove(...)

    and check these log messages out, and then figure what else you might have done wrong.

    2nd
    you really shouldn't check objects by their names like that

    3rd
    you shouldn't use lists for arbitrary removals
    imagine if you were really dumb and had a list for groceries
    1. mushrooms
    2. tomatoes
    3. flour
    4. whiskey
    5. potatoes
    6. cucumbers

    now imagine mom tells you to not buy whiskey, because she suddenly realizes you're too young or whatever
    well, a computer goes like this
    1. mushrooms, ok that's not whiskey
    2. tomatoes, not whiskey either
    3. flour, hmm, still nothing
    4. whiskey, okay this is whiskey, but wait! if I scrap this I have this empty space, nah I have to fill this up now
    5. potatoes, okay I'm moving this up, aaand
    6. cucumbers, ok finished

    what you want is a dedicated structure that can remove things without having to mindlessly traverse through all of it.

    you know what? if your list is really small, 10 elements tops, then it's fine
    if not, you need to revise your approach

    4th
    please please use code tags for your code examples
     
  3. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,066
    I see mainly two ways of handling this:
    - When destroying the object, somehow inform your tracking script, so that it can remove it from the list. This could be a component that sends an event in
    OnDestroy
    (and/or
    OnDisable
    ), which the tracking script can subscribe to in
    OnTriggerEnter2D
    (and unsubscribe from in
    OnTriggerExit2D
    ).
    - When you iterate through the list, check for and remove all elements that are null. I prefer a reverse for in this case, since it easily lets you remove elements as you iterate:
    Code (CSharp):
    1. for (var i = list.Count - 1; i >= 0; i--) {
    2.     var element = list[i];
    3.     if (element == null) {
    4.         list.RemoveAt(i);
    5.         continue;
    6.     }
    7.  
    8.     // Do something with the existing element
    9. }
    It's not only fine, it's actually better for small lists. If you have only a few dozen elements, a linear search will use less overhead and often be faster than more complex algorithms/data structures.
     
    skyLark9 likes this.
  4. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    I would advise an array anyway, but true.