- Home /
Destroying clones of a prefab from another script
i have a gun shooting bullets and i do not want those bullets to run indefinitely so i want to destroy them. i have 2 scripts:
Spawner (spawns the bullets from a bullet prefab: the gun)
bullet = (GameObject) Instantiate(bulletPrefab, transform.position , Quaternion.Identity);
Destroyer( destroys bullets if they go too far away )
public Spawner bulletSpawner;
if (bulletSpawner.bullet.transform.position.z<-1000) { Destroy(bulletSpawner.bullet); }
how can i reference the bullets from the destroyer so it actually destroys the clones? (if i fire 1 bullet it works fine, but i keep firing, it doesnt work)
Answer by Slink472 · Oct 25, 2019 at 03:57 AM
You can add a reference from the spawner script to send the information about the bullets it creates to the destroyer. Then, the destroyer can make a list of these bullets and continuously check how far the bullets have moved before it destroys them. For instance:
Spawner script:
public GameObject bulletPrefab;
public Destroyer destroyer;
void Update()
{
// Insert whatever conditions you need to meet to fire the bullet
SpawnBullet();
}
void SpawnBullet()
{
bullet = GameObject Instantiate(bulletPrefab, transform.position, Quaternion.Identity);
destroyer.SendBullet(bullet);
}
And your destroyer script might have:
public list<GameObject> bullets;
void Update()
{
foreach(GameObject bullet in bullets)
{
if(bullet.transform.position.z < -1000)
{
Destroy(bullet);
bullets.Remove(bullet);
}
}
}
public void SendBullet(GameObject bullet)
{
bullets.Add(bullet);
}
Answer by Rachini · Oct 25, 2019 at 09:04 AM
@Slink472 the solution you mentioned is working. but i am getting this error:
InvalidOperationException: Collection was modified; enumeration operation may not execute. System.ThrowHelper.ThrowInvalidOperationException (System.ExceptionResource resource) (at :0) System.Collections.Generic.List`1+Enumerator[T].MoveNextRare () (at :0) System.Collections.Generic.List`1+Enumerator[T].MoveNext () (at :0) Destroyer.Update () (at Assets/Scenes/Destroyer.cs:26)
what does this mean ? and how to fix it ?
I believe this occurs when you remove elements from a list that you are iterating on with a loop. One option you could try is to copy the list, iterate on the copy but apply the destruction/removal to the original. You should also iterate from end to beginning so that as you remove elements, it does not mix up the index of the next processed elements. Hope that helps!
hi @graylightgames , im pretty overwhelmed by this since this is a new concept for me. can you explain more on how to script that please ?
Answer by GrayLightGames · Nov 02, 2019 at 04:11 AM
No problem @Rachini, things can be overwhelming but hang in there and they will make sense! Just to elaborate a little bit... when you remove items from a list mid-loop, it alters the list and C# has a hard time deciding how to continue looping... So to avoid this, you can copy the list and loop on the copy. Then you can use the items from the copy to reference the original list and modify it. So since you aren't modifying the list that is used for the loop, C# stays happy. When I mentioned end to beginning, I didn't pay attention that you're using a foreach... so you can disregard for this case. If you use a standard for loop, you will refer to the list items by their index, so if you remove the first object, all the other objects have their indexes updated so the list copy and the original will have different indexes and be out of sync. If you start at the end of the list and move backward, this isn't an issue because removing a list item only effects items that are after it. If that is confusing wording, please don't pay attention. If you Google "modifying a collection from a loop", you will see some more detailed discussions of what issues can be caused and what solutions are best. I find the loop copy simple and safe, so that's what I normally do. Hopefully this will resolve the issue for you though and you can get back to the fun stuff!
Here's a code example for your case:
void Update()
{
//Make a temporary copy of the original List object
bulletsCopy = new List<GameObject>(bullets);
//Iterate on the copy because it will be unchanged during our loop
foreach (GameObject bullet in bulletsCopy)
{
if (bullet.transform.position.z < -1000)
{
Destroy(bullet);
//Remove from the original list, which works because
//this bullet object exists in both the copy and the original
bullets.Remove(bullet);
}
}
}
@graylightgames a Very articulate and elaborate answer ! you explained the stuff very nicely and the thought process behind it also ! really awesome of you.thanks a lot !
No problem at all, it was a confusing issue the first time I encountered it as well... good luck with your project!
Your answer
Follow this Question
Related Questions
How to destroy bullets? 2 Answers
Destroying clones? 1 Answer
Destroying Children Individually (Horrible..) 2 Answers
How to determine which GameObject to destroy? 2 Answers
Script won't destroy prefab clones when overlapping... plz help 1 Answer