[SOLVED] Instantiate creates endless stream of objects

Hi, I cant for the life of me figure out why my code is instantiating so many objects when I have a coroutine that makes you wait every 5 seconds before you can fire again. The first object takes about 5 seconds to instantiate and then it is just a constant stream of instantiated objects.
Heres what it looks like: it should just be one sphere at a time


Here’s my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gorffrey_Data : MonoBehaviour
{
    public GameObject EmpathySphere;
    public GameObject HateSphere;
    public Transform EnemyPosition;
    public bool canFire = true;

    //maybe have an enemymanager script that handles this stuff later
    public int enemyMaxHealth = 20;
    public int enemyCurrentHealth;
    public int enemyStartingHealth = 5;

    // Start is called before the first frame update
    // Update is called once per frame
    void Update()
    {
       
        if(canFire == true && enemyCurrentHealth != enemyMaxHealth)
        {
            Instantiate(HateSphere, EnemyPosition.position, EnemyPosition.rotation);
        }

        canFire = false;

        StartCoroutine(RandomFire());
    }

    //coroutine to fire bullets in random interval
    IEnumerator RandomFire()
    {


        yield return new WaitForSeconds(5);
        canFire = true;
    }
}

You are starting a new coroutine every frame so once five seconds has passed after the first update, your canFire boolean is being set to true every few milliseconds depending on the frame time when it was started.

You could change your logic a bit and only start a coroutine when you instantiate, like so

private void Update()
{

    if (canFire == true && enemyCurrentHealth != enemyMaxHealth)
    {
        Instantiate(HateSphere, EnemyPosition.position, EnemyPosition.rotation);

        canFire = false;

        StartCoroutine(RandomFire());
    }


}

//coroutine to fire bullets in random interval
IEnumerator RandomFire()
{
    yield return new WaitForSeconds(5);
    canFire = true;
}

Although you don’t really need a coroutine here when you could just use a timer in the update method. I’m not sure on your thinking or logic with your if statement though. You have is enemyCurrentHealth != enemyMaxHealth but assuming that enemyCurrentHealth is set to the startingHealth of 5, then it doesn’t ever equal the max health of 20.

thanks so much it works! ya that was dumb logic on my part i realized the coroutine starts every frame. And the if statement logic is that way because the point of combat in my game is to heal your opponents to “beat” them so the logic is kinda flipped.