Destroy prefabs after they have been instantiated (C#)
Hello my friend who is reading this! I got a problem with some of my code. I have created a power up prefab that is supposed to destroy all enemy prefabs that are out on the map. I'm spawning out new enemies every 3 to 5 seconds. Now when I run over the power up, it only destroys the enemies that were instantiated before the power up was used and spawned.
How can I destroy all enemies out on the map including the new ones that spawned in after the power up spawns in?
Code for picking up the power up: (Note that the power up is used directly when you trigger/collide with it)
using UnityEngine;
using System.Collections;
public class PickUpScript : MonoBehaviour
{
void OnTriggerEnter2D(Collider2D col)
{
if(col.gameObject.tag == "PowerUp1")
{
Destroy(GameObject.FindGameObjectWithTag("EnemyBouncing"));
Destroy(GameObject.FindGameObjectWithTag("EnemyFollow"));
Destroy(GameObject.FindGameObjectWithTag("PowerUp1"));
}
}
Code for spawning out enemies:
using UnityEngine;
using System.Collections;
public class EnemySpawn : MonoBehaviour
{
// EnemyPrefabs
public GameObject EnemyBouncingPrefab;
public GameObject EnemyFollowPrefab;
//Show where spawn is prefab
public GameObject ShowEnemySpawn;
// Array of spawn points
public Transform[] spawnPoints;
// Borders
public Transform borderTop;
public Transform borderBottom;
public Transform borderLeft;
public Transform borderRight;
void Start ()
{
// Starts a coroutine function for spawning bouncing enemies
StartCoroutine(SpawnBouncingEnemy());
// Spawn only one follow enemy
InvokeRepeating("SpawnEnemyFollow", Random.Range(2, 5), 0);
}
// Spawn a Bouncing enemy
IEnumerator SpawnBouncingEnemy()
{
//Wait 3 seconds when game starts to spawn a ball
yield return new WaitForSeconds(Random.Range(3, 5));
while(true)
{
//Calls the function to set random position
Vector2 spawnPoint = RandomPointWithinBorders();
// Show spawn location for one second
Object marker = Instantiate(ShowEnemySpawn, spawnPoint, Quaternion.identity);
yield return new WaitForSeconds(1);
Destroy(marker);
// Spawn enemy
Instantiate(EnemyBouncingPrefab, spawnPoint, Quaternion.identity);
yield return new WaitForSeconds(Random.Range(4, 6));
}
}
Vector2 RandomPointWithinBorders()
{
//Code that will spawn a bouncing ball and ShowSpawn at a random position inside the borders
Vector2 random = new Vector2();
random.x = (int)Random.Range(borderLeft.position.x, borderRight.position.x);
random.y = (int)Random.Range(borderBottom.position.y, borderTop.position.y);
return random;
}
void SpawnEnemyFollow()
{
// Find a random index between zero and one less than the number of spawn points.
int spawnPointIndex = Random.Range (0, spawnPoints.Length);
// Create an instance of the enemy prefab at the randomly selected spawn point's position and rotation.
Instantiate (EnemyFollowPrefab, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
}
}
I'm so grateful for every help that I can get! You guys are the best! Been trying to solve this for ages, but haven't found any great answers yet.
Answer by TreyH · Mar 12, 2016 at 02:44 PM
Instead of using the tag system, you might want to just keep track of your spawned enemies:
using System.Collections.Generic;
So we'll just add new enemies to a list:
// Keep track of enemies we've created across all spawners
public static List<GameObject> activeEnemies;
// Start
void Awake()
{
// Create the list
activeEnemies = new List<GameObject>();
}
// Destroy all existing enemies
public static void DestroyActiveEnemies()
{
// Prevent ourselves from tinkering with a List during its enumeration
int currentCount = activeEnemies.Count;
// Go through and destroy each one
for (int k=0; k<currentCount; k++)
{
Destroy(activeEnemies[k]);
}
// Clear the list up to this point
activeEnemies.RemoveRange(0, currentCount);
}
So for each of your spawning functions, add the new enemy to this list:
// Instantiate
GameObject newEnemy = (GameObject) Instantiate(EnemyBouncingPrefab, spawnPoint, Quaternion.identity);
// Add them to our list
activeEnemies.Add(newEnemy);
// Yield for the coroutine (Note that this will cause GC (due to the "new" part),
// but you can declare a WaitForSeconds instance to prevent this
yield return new WaitForSeconds(Random.Range(4, 6));
Causing your pickup script's Trigger code to become:
public class PickUpScript : MonoBehaviour
{
void OnTriggerEnter2D(Collider2D col)
{
if(col.gameObject.tag == "PowerUp1")
{
// Call the function we just wrote
EnemySpawn.DestroyActiveEnemies();
}
}
}