Search Unity

Question [SOLVED] Instantiate creates endless stream of objects

Discussion in 'Scripting' started by larrypickle, Jul 30, 2020.

  1. larrypickle

    larrypickle

    Joined:
    Oct 8, 2019
    Posts:
    8
    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
    bug23.JPG
    Here's my code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Gorffrey_Data : MonoBehaviour
    6. {
    7.     public GameObject EmpathySphere;
    8.     public GameObject HateSphere;
    9.     public Transform EnemyPosition;
    10.     public bool canFire = true;
    11.  
    12.     //maybe have an enemymanager script that handles this stuff later
    13.     public int enemyMaxHealth = 20;
    14.     public int enemyCurrentHealth;
    15.     public int enemyStartingHealth = 5;
    16.  
    17.     // Start is called before the first frame update
    18.     // Update is called once per frame
    19.     void Update()
    20.     {
    21.        
    22.         if(canFire == true && enemyCurrentHealth != enemyMaxHealth)
    23.         {
    24.             Instantiate(HateSphere, EnemyPosition.position, EnemyPosition.rotation);
    25.         }
    26.  
    27.         canFire = false;
    28.  
    29.         StartCoroutine(RandomFire());
    30.     }
    31.  
    32.     //coroutine to fire bullets in random interval
    33.     IEnumerator RandomFire()
    34.     {
    35.  
    36.  
    37.         yield return new WaitForSeconds(5);
    38.         canFire = true;
    39.     }
    40. }
    41.  
     
  2. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    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
    Code (CSharp):
    1. private void Update()
    2. {
    3.  
    4.     if (canFire == true && enemyCurrentHealth != enemyMaxHealth)
    5.     {
    6.         Instantiate(HateSphere, EnemyPosition.position, EnemyPosition.rotation);
    7.  
    8.         canFire = false;
    9.  
    10.         StartCoroutine(RandomFire());
    11.     }
    12.  
    13.  
    14. }
    15.  
    16. //coroutine to fire bullets in random interval
    17. IEnumerator RandomFire()
    18. {
    19.     yield return new WaitForSeconds(5);
    20.     canFire = true;
    21. }
    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.
     
  3. larrypickle

    larrypickle

    Joined:
    Oct 8, 2019
    Posts:
    8
    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.