- Home /
How to remove a specific prefab from a List?
Hi all, I'm new to Unity and coding, and in my prototype (basically a Space Invader -like where you are a static cannon that can only rotate) I have a Game Object called EnemySpawner that generates new enemies from a List of prefabs. WIth time, the Time.timeScale increases, and the EnemySpawner adds a new enemy prefab (called EnemySlowDown) to the List. This enemy, when hit, halves the increase of the Time.timeScale, giving the player some breathing room. Obviously, once the EnemySlowDown instance is destroyed, I want it to be removed from the list, to be added on a later stage, and the only way I was able to do this, was by "hard coding" the RemoveAt function at index position 3, just because I knew that once added, EnemySlowDown would have been at that position.
I'd like to use List.Remove() but it's not working for me: i tried writing EnemySlowDown as argument, I tried storing a reference to the class EnemySlowDown and then passing that as an argument, and even created a public function inside EnemySpawner with a for statement that loops through all the elements in the List and removes the one with the correct string name passed into the function.
I hope you can help me, because I even forgot to eat XD.
Here's the code of the Enemy Spawner
public class EnemySpawner : MonoBehaviour
{
[SerializeField] public List<GameObject> enemyPrefab = null;
[SerializeField] GameObject enemySlowDown = null;
[SerializeField] private float _timeToSpawn = 0;
[SerializeField] private float _timeToNextSpawn = 0;
private float _timeScaleToAddSlowDownEnemy = 1.2f;
private float _minX = -2.5f;
private float _maxX = 2.5f;
void Update()
{
SpawnEnemy();
AddSlowDownEnemy();
}
private void SpawnEnemy()
{
if (Time.time >= _timeToSpawn)
{
Instantiate(
enemyPrefab[Random.Range(0, enemyPrefab.Count)],
new Vector2(Random.Range(_minX, _maxX),
transform.position.y),
transform.rotation);
_timeToSpawn += _timeToNextSpawn;
}
}
private void AddSlowDownEnemy()
{
if (Time.timeScale >= _timeScaleToAddSlowDownEnemy &&
!enemyPrefab.Contains(enemySlowDown))
{
enemyPrefab.Add(enemySlowDown);
}
}
public void RemoveFromSpawner(string objectName)
{
for (int i = 0; i < enemyPrefab.Count; i++)
{
if (enemyPrefab[i].name == objectName)
{
enemyPrefab.Remove(enemyPrefab[i]);
}
}
And the EnemySlowDown one:
public class Enemy_SlowDown : MonoBehaviour
{
[SerializeField] AudioClip[] deathSound = null;
[SerializeField] float _enemySpeed = 5f;
EnemySpawner enemySpawner;
GameState gameState;
Rigidbody2D rB;
void Awake()
{
enemySpawner = FindObjectOfType<EnemySpawner>();
rB = GetComponent<Rigidbody2D>();
gameState = FindObjectOfType<GameState>();
}
void Start()
{
rB.velocity = -transform.up * _enemySpeed;
}
void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Projectile"))
{
AudioSource.PlayClipAtPoint(deathSound[Random.Range(0, deathSound.Length)], Camera.main.transform.position);
gameState.AddToScore(1);
SlowDown();
}
Destroy(gameObject);
}
void SlowDown()
{
float _extraSpeed = Time.timeScale - 1;
float _newSpeed = 1 + (_extraSpeed * .5f);
Time.timeScale = _newSpeed;
enemySpawner.enemyPrefab.RemoveAt(3);
}
}
Answer by logicandchaos · Aug 30, 2020 at 02:44 PM
When comparing strings don't use == use String.Compare, also you shouldn;t be using a string to identify the object anyways. You can compare with the actual game object which will be much more accurate.
public void RemoveFromSpawner(GameObject gameObject)
{
enemyPrefab.Remove(gameObject);
}
You can also do this to check if it's in the list 1st: public void RemoveFromSpawner(GameObject gameObject) { if(enemyPrefab.Contains(gameObject)) enemyPrefab.Remove(gameObject); }
I tried passing in the gameObject name, but it doesn't work, even when caching it into a serialized field where i drop the prefab to remove, or with a normal reference on top.
I worked around the problem with a very anelegant way
public void RemoveFromSpawner(string objectName)
{
for (int i = 0; i < enemyPrefab.Count; i++)
{
if (enemyPrefab[i].name == objectName)
{
enemyPrefab.RemoveAt(i);
}
}
}
Didn't you ask this also in the forums? It would be polite to say so, so that people won't answer the same question in 2 places... Link: https://forum.unity.com/threads/how-to-remove-an-object-from-a-list-of-prefabs.960916/
Yeah I did, not on purpose though. When trying to post it here, the page was giving me loading errors, and when decided to proceed and use the forum, I found out that the post was posted here, too.
Anyway, @logicandchaos , I implemented your suggestion about the Compare method in my new function
public void RemoveFromSpawner(string objectName)
{
for (int i = 0; i < enemyPrefab.Count; i++)
{
if (String.Compare(enemyPrefab[i].name, objectName) == 0)
{
enemyPrefab.RemoveAt(i);
}
}
}
Your answer
Follow this Question
Related Questions
i have a problem with reloading with Time.time 2d game c# Unity 2020.2 1 Answer
How would one go about making an asteroid field in a circle around an empty object in 2D? 0 Answers
How would i calculate the size of a 2D area closed off by multiple colliders? 1 Answer
OnCollisionStay2D deactivates after a short amount of time 1 Answer
What is the purpose of this function? "protected virtual void Init() { }" 1 Answer