Search Unity

How to Destroy all Objects from a List

Discussion in 'Scripting' started by Mashimaro7, Sep 24, 2020.

  1. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    727
    I have a script that spawns a random amount of objects, and then adds each one to a list(not super familiar with lists, so you can tell me if I did this part wrong too haha) here's my script,
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class TreeGame : MonoBehaviour
    6. {
    7.     private Animator anim1;
    8.     private Animator anim2;
    9.     bool treeShaking;
    10.     [SerializeField]private GameObject[] objectsToFall;
    11.     public int randomX, randomY;
    12.  
    13.     void Start()
    14.     {
    15.         anim1 = GetComponent<Animator>();
    16.         anim2 = GameObject.Find("cartoon tree leaves").GetComponent<Animator>();
    17.         anim1.speed = 0;
    18.         anim2.speed = 0;
    19.     }
    20.  
    21.     private void OnMouseDown()
    22.     {
    23.         if (!treeShaking)
    24.         {
    25.             StartCoroutine(TreeShake());
    26.         }
    27.     }
    28.  
    29.     IEnumerator TreeShake()
    30.     {
    31.         List <GameObject> list = new List<GameObject>();
    32.         int objectsNum = Random.Range(randomX, randomY);
    33.         treeShaking = true;
    34.         if (anim1.speed == 0 || anim2.speed == 0)
    35.         {
    36.            
    37.             anim1.speed = 1;
    38.             anim2.speed = 1;
    39.         }
    40.         else
    41.         {
    42.             anim1.Play("treeLogAnim", 0, 0);
    43.             anim2.Play("treeAnim", 0, 0);
    44.         }
    45.         for (int i = 0; i < objectsNum; i++)
    46.                 {
    47.             yield return new WaitForSeconds(.5f);
    48.             int randomNum = Random.Range(0, objectsToFall.Length);
    49.             Instantiate(objectsToFall[randomNum],transform.position,Quaternion.identity);
    50.             list.Add(objectsToFall[randomNum]);
    51.                 }
    52.         print(list.Count);
    53.  
    54.         yield return new WaitForSeconds(2);
    55.         treeShaking = false;
    56.     }
    57. }
    58.  
    My question is, how do I interact with the objects of a list? I know how to do a for loop for an array, but how does it work with lists? I just want to destroy all the objects that have been added to the list before spawning new ones. I tried a foreach loop, (var object in list) but it just simply destroyed the object the script is on lol.

    Thanks in advance
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    The syntax is identical, except that you use .Count instead of .Length.

    Post that code so we can tell you what went wrong with it
     
    Mashimaro7 likes this.
  3. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    727
    I figured out I typed Destroy(gameObject) instead of Destroy(object) lol. But about the syntax, so, it would be like, list in a for loop?

    Edit: Okay, I tried changing it to Destroy(objects), but now it's saying it can't destroy assets. I think it's adding the prefab from the assets to the list rather than the spawned object. Here's my script,
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class TreeGame : MonoBehaviour
    6. {
    7.     private Animator anim1;
    8.     private Animator anim2;
    9.     bool treeShaking;
    10.     [SerializeField]private GameObject[] objectsToFall;
    11.     public int randomX, randomY;
    12.  
    13.     void Start()
    14.     {
    15.         anim1 = GetComponent<Animator>();
    16.         anim2 = GameObject.Find("cartoon tree leaves").GetComponent<Animator>();
    17.         anim1.speed = 0;
    18.         anim2.speed = 0;
    19.     }
    20.  
    21.     private void OnMouseDown()
    22.     {
    23.         if (!treeShaking)
    24.         {
    25.             StartCoroutine(TreeShake());
    26.         }
    27.     }
    28.  
    29.     IEnumerator TreeShake()
    30.     {
    31.         List <GameObject> list = new List<GameObject>();
    32.         int objectsNum = Random.Range(randomX, randomY);
    33.         treeShaking = true;
    34.         if (anim1.speed == 0 || anim2.speed == 0)
    35.         {
    36.            
    37.             anim1.speed = 1;
    38.             anim2.speed = 1;
    39.         }
    40.         else
    41.         {
    42.             anim1.Play("treeLogAnim", 0, 0);
    43.             anim2.Play("treeAnim", 0, 0);
    44.         }
    45.         for (int i = 0; i < objectsNum; i++)
    46.                 {
    47.             yield return new WaitForSeconds(.5f);
    48.             int randomNum = Random.Range(0, objectsToFall.Length);
    49.             Instantiate(objectsToFall[randomNum],transform.position,Quaternion.identity);
    50.             list.Add(objectsToFall[randomNum]);
    51.                 }
    52.         foreach(var objects in list)
    53.         {
    54.             Destroy(objects);
    55.         }
    56.  
    57.         yield return new WaitForSeconds(2);
    58.         treeShaking = false;
    59.     }
    60. }
    61.  
    So, how do I make it add the spawned prefab to the list?
     
    Last edited: Sep 25, 2020
  4. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    727
    Sorry for the spam, well, I got it working, again. Lol, here's my script for anyone interested!

    Basically I needed to list.Add(Instantiate--) rather than instantiate then add. Also I was struggling with deleting after that, basically just check if the list isn't null, and if it isn't, run a for loop with list.Count. After the for loop, clear the list. I was struggling because I was trying to clear the list during the loop, and it was getting confused because list.Count turns to 0 when the list is cleared, so it exited the loop early, after only destroying two objects.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class TreeGame : MonoBehaviour
    6. {
    7.     private Animator anim1;
    8.     private Animator anim2;
    9.     bool treeShaking;
    10.  
    11.     public Transform[] transforms;
    12.     [SerializeField]private GameObject[] objectsToFall;
    13.     public int randomX, randomY;
    14.     public List<GameObject> list = new List<GameObject>();
    15.  
    16.     [SerializeField] Sprite[] sprites;
    17.  
    18.     void Start()
    19.     {
    20.         anim1 = GetComponent<Animator>();
    21.         anim2 = GameObject.Find("cartoon tree leaves").GetComponent<Animator>();
    22.         anim1.speed = 0;
    23.         anim2.speed = 0;
    24.     }
    25.  
    26.     private void OnMouseDown()
    27.     {
    28.         if (!treeShaking)
    29.         {
    30.             StartCoroutine(TreeShake());
    31.         }
    32.     }
    33.  
    34.     IEnumerator TreeShake()
    35.     {
    36.        
    37.        
    38.         if (list != null)
    39.         {
    40.             for (int i = 0; i < list.Count; i++)
    41.             {
    42.                 Destroy(list[i].gameObject);
    43.             }
    44.             list.Clear();
    45.         }
    46.         int objectsNum = Random.Range(randomX, randomY);
    47.         treeShaking = true;
    48.  
    49.         if (anim1.speed == 0 || anim2.speed == 0)
    50.         {
    51.            
    52.             anim1.speed = 1;
    53.             anim2.speed = 1;
    54.         }
    55.  
    56.         else
    57.         {
    58.             anim1.Play("treeLogAnim", 0, 0);
    59.             anim2.Play("treeAnim", 0, 0);
    60.         }
    61.        
    62.         for (int i = 0; i < objectsNum; i++)
    63.                 {
    64.             yield return new WaitForSeconds(.5f);
    65.             int randomNum = Random.Range(0, objectsToFall.Length);
    66.  
    67.             int randomSpotter = Random.Range(0, transforms.Length);
    68.             if (randomSpotter == 0)
    69.             {
    70.                 list.Add(Instantiate(objectsToFall[randomNum], transforms[0].position, Quaternion.identity));
    71.             }
    72.             if (randomSpotter == 1)
    73.             {
    74.                 list.Add(Instantiate(objectsToFall[randomNum], transforms[1].position, Quaternion.identity));
    75.             }
    76.             if (randomSpotter == 2)
    77.             {
    78.                 list.Add(Instantiate(objectsToFall[randomNum], transforms[2].position, Quaternion.identity));
    79.             }
    80.             list[i].GetComponent<SpriteRenderer>().sprite = sprites[Random.Range(0, sprites.Length)];
    81.                 }
    82.         yield return new WaitForSeconds(1);
    83.  
    84.  
    85.        
    86.         treeShaking = false;
    87.     }
    88. }
    89.  
     
    Last edited: Sep 25, 2020
    allpublic likes this.
  5. pingor2

    pingor2

    Joined:
    Oct 20, 2018
    Posts:
    1
    Well it has been 2 years since it was asked but as i understand a list works like "first in first out" so you need to loop and remove the element. then destroy it, so the second element becomes the first and repeat until it´s empty, also in my expirience a foreach loop will fail something like the operation can not be completed if the collection dimention is modified,
     
    Hackman49 likes this.
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,428
    You can do that if you wanted the absolute worst performance possible so not sure the necro has good advice.

    You should process it in reverse, removing the end one as that doesn't require the whole list to be copied down; that should be obvious really. That said, why would you delete/remove/delete/remove? Surely you'd just iterate the list, deleting the objects it contains, then when done, simply clear the list.
     
    Mashimaro7 likes this.
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    ALL of this stuff has actual documentation online, so there's no reason for you to go around with completely incorrect understandings floating around your brain. That's just ... silly.

    https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1

    Having incorrect things in your mind is only going to confuse and slow you down. Don't allow it.

    If the docs don't do it for you, work through a few tutorials. Read some example code that uses the collection in question.

    Also, for a "first in first out" collection, that is called a Queue<T> and guess what? There's online docs for that too... yay!!

    https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1?view=net-6.0