-2

I have a question. Im trying to create a spawner with max limit of 4 spawns. But if a spawn is destroyed I want to start the spawning again up until the number reaches max again. Below I have the code but my spawner just keeps spawning objects over the limit. Can somebody help me?

public class EnemySpawner : MonoBehaviour
{

    [SerializeField] GameObject enemyPrefab;

    [SerializeField] private float spawnRate = 4f;
    [SerializeField] int spawns;

    private int xPos;
    private int zPos;

    private int spawnsLimit = 4;
    

    private void Start()
    {
        spawns = GameObject.FindGameObjectsWithTag("Enemy").Length;

        if (spawns < spawnsLimit)
        {
            StartCoroutine(EnemySpawn());
        }
        else if (spawns > spawnsLimit)
        {
            StopCoroutine(EnemySpawn());
        }
        
    }

    IEnumerator EnemySpawn()
    {
            xPos = Random.Range(-20, 20);
            zPos = Random.Range(-20, 20);

            Instantiate(enemyPrefab, new Vector3(xPos, 1, zPos), Quaternion.identity);
            yield return new WaitForSeconds(spawnRate);
            StartCoroutine(EnemySpawn());
    }
n0rd
  • 11,850
  • 5
  • 35
  • 56
  • Can you paste the code here? – Pawel Oct 23 '22 at 22:20
  • Where do you increment `spawns`? – Pawel Oct 23 '22 at 22:26
  • I try to equal spawns with number of objects wit tag ''Enemy'' – Raf Kam Oct 23 '22 at 22:37
  • Print the value to the console and track the issue down. Place some breakpoints, use a debugger. There is not enough data to solve the issue without seeing all your code – Pawel Oct 23 '22 at 22:40
  • Aside from this, there is no more code connected to the spawner. The Prefab is also tagged ''Enemy'' without any typo, so basically I think the problem is that Unity does not count the number of objects with the ''Enemy'' tag on the scene. – Raf Kam Oct 23 '22 at 22:51

1 Answers1

0

The first the in understanding why this isn’t working is realising that the Start method is called just once. In that method you then do the (fairly costly) process of searching for objects with a specific tag. Being that the game has just started, the number of objects found will be zero, and the first part of your if-else statement will run. The second part will never be reached.

When you’re in the coroutine, you’re then waiting an amount of time given by the spawn rate, and adding a new enemy object. There’s no further checks in the coroutine, which is exactly where the checks should be.

To try and keep the code as similar as possible, I’d change it up to something like (untested):

public class EnemySpawner : MonoBehaviour
{
    public static EnemySpawner instance get; private set; }

    [SerializeField] GameObject enemyPrefab;
    [SerializeField] private float spawnRate = 4f;
    [SerializeField] int spawns;

    private int spawnsLimit = 4;
    public bool isSpawning { get; private set; }
    public int numberOfEnemies { get; private set; }

    private void Start()
    {
        if (instance == null )
            instance = this;
        isSpawning = true;
        StartCoroutine(EnemySpawn());
    }

    public void EnemyDestroyed()
    {
        —numberOfEnemies;
    }

    IEnumerator EnemySpawn()
    {
        while (isSpawning)
        {
            if ( numberOfEnemies < spawnsLimit )
            {
                var pos = new Vector3 (
                    Random.Range(-20, 20), 1, Random.Range(-20, 20) );
                Instantiate(enemyPrefab, pos, Quaternion.identity);
                numberOfEnemies++;
            }
            yield return new WaitForSeconds(spawnRate);
        }
    }
}

Now, whenever an enemy dies, that code should call EnemySpawner.instance.DestroyEnemy(). That way, the spawner will know how many enemies are currently in play, and only spawn a new one after the spawn time limit.

The exact logic in the coroutine is simply an example. This will always wait a minimum of 4 seconds after a new enemy should be spawned. But it should do the trick and suit your situation.

Milan Egon Votrubec
  • 3,696
  • 2
  • 10
  • 24