- Home /
Destroy all GameObjects at once
Let's say I want to destroy all enemies at once. One thing I can do is use GameObject.FindGameObjectsWithTag, then run through the returning array and Destroy each returned gameObject.
That's the better way to do it? There's something else? SendMessage has nothing to do with this?
Answer by YesNoKonrad · Feb 23, 2015 at 07:33 PM
Update (2021-02-09): This answer is quite unsophisticated. It is correct only in regards to the question and should not be considered a general solution. Please read through the comment section as well.
I suppose you have an Enemy script?
To be sure to get any enemy destroyed you could declare a static generic List myEnemies.
(needs System.Generic... something along those lines, you will see it via code completion, there also is a tutorial about that in the scripting section).
Then you would implement a static function within your class which you would call for example RemoveAllEnemies
static void RemoveAllEnemies()
{
foreach(GameObject go in myEnemies)
{
myEnemies.Remove(go); // else there will be pointer to null
GameObject.Destroy(go);
}
}
you would call this function like this: Enemy.RemoveAllEnemies();
A static function only exists within the class, not the instantiated objects. to access the function it has to be public... i think.
I should also mention that you would need to actualy add the object to the list on creation of the object. best done in the awake() function.
Pretty much everything is faster than finding objects at runtime with Find
Yes, its cheaper, and it will become even more cheap if a pooling solution was used to avoid the dreaded Garbage Collector, which kills performance. So, ins$$anonymous$$d of using Destroy(GameObject), you use gameObject.SetActive(false) to deactivate the enemies (no garbage collection). Of course this means that enemies can be reused with gameObject.SetActive(true) ins$$anonymous$$d of spawning them.
A number of free and paid pool solutions are available in the asset store:
Yeah pako +1. that would be the next step. saw other threads about that topic. i think i marked my answer as changeable from anyone... so if someone cares about changing/ improving details of the given answer or adding to it, feel free.
The Answer is wrong.
You must go backwards through the list.
static void RemoveAllEnemies()
{
for (int i = myEnemies.Count; i >= 0; i--)
{
GameObject go = myEnemies[ i ];
myEnemies.Remove(go);
GameObject.Destroy(go);
}
}
The answer is not wrong. It's quite crude but it works. And though I agree that it's not a good solution, your improvement is only so much better considering you still don't use pooling, the function is static and not thread safe and all the other problems that exist with the solution that are far more important.
Answer by ExtremePowers · Feb 23, 2015 at 07:39 PM
You could do something like this:
void Start() {
EM = new GameObject();
EM.name = "EnemyManager";
//Spawn 15 enemies and attach them to EnemyManager
for (int i=0; i < 15; i++) {
GameObject Enemy = GameObject.Instantiate(EnemyPrefab, Vector3.zero, Quaternion.identity;
Enemy.transform.parent = EM.transform;
}
}
private GameObject EM;
public GameObject EnemyPrefab;
public bool something;
void Update() {
if (something) {
GameObject.Destroy(EM);
}
}
Nice solution, but maybe it would be more complete if you included in your answer some details about which GameObject this script would be attached on, and also how a new Enemy$$anonymous$$anager would be created, if it's needed further down the game. Destroying all the enemies at once, in one point in the game, doesn't mean that no more enemies will be spawned further down the game ;-)
You could do this ins$$anonymous$$d:
void SpawnEnemy() {
if (!E$$anonymous$$) {
E$$anonymous$$ = new GameObject();
E$$anonymous$$.name = "Enemy$$anonymous$$anager";
}
for (int i=0; i < 15; i++) {
GameObject Enemy = GameObject.Instantiate(EnemyPrefab, Vector3.zero, Quaternion.identity;
Enemy.transform.parent = E$$anonymous$$.transform;
}
}
The script could be attached to an empty gameobject.
Answer by pidgi2001 · Oct 17, 2020 at 09:53 PM
May I suggest one simple solution? Not tested though... Put all the GameObjects as children of one GameObject (say, a ‘big’ object named EnemyHerd, and every Enemy is a child of the big one.) Then, Destroy() the parent.
Answer by siaran · Feb 23, 2015 at 05:59 PM
I'd avoid using GameObject.Find and its derivatives as much as possible and instead keep a list of enemies in some kind of manager class somewhere.
Other then that, if you want to destroy all enemies I don't think there is a better way then looping through your list of enemy gameObjects and calling Destroy on all of them.
Answer by RedClawStudios · Feb 09, 2021 at 05:51 PM
Here is what I have used iterating backwards (@BergOnTheJob I tried yours but I think iteration is going wrong because you use count and it seems to be checked each loop and it changes). Also need to minus 1 to convert count to item number in list.
int maxItemId = enemyList.Count-1;
for (int i = maxItemId ; i >= 0; i--)
{
GameObject go = enemyList[i];
enemyList.Remove(go);
Destroy(go);
}
Your answer
Follow this Question
Related Questions
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers
Problem with timed code-execution (audioplay and object destruction) 1 Answer
Trying to make a simple inventory: 0 Answers
Destruct gameobject by call from another script 1 Answer
GameObject.FindGameObjectsWithTag still finding destroyed object (C#) 1 Answer