Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

csharp how can I fire bullets from a turret every 2 seconds rather than continously?

Discussion in 'Scripting' started by Tezelian, Apr 25, 2014.

Thread Status:
Not open for further replies.
  1. Tezelian

    Tezelian

    Joined:
    Oct 22, 2013
    Posts:
    256
    Basically I have a turret that keeps on shooting white balls every frame which forms a long white line

    I am guessing this is because update function updates something every frame which I don't want so I have to create another fucntion ienumerator on csharp?

    This is what I have so far

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class bullet : MonoBehaviour {
    5.  
    6.     public Transform spawnn;
    7.     public GameObject fire;
    8.  
    9.     void Update () {
    10.    
    11.         DoStuff ();
    12.  
    13.     }
    14.  
    15.  
    16.     IEnumerator DoStuff()
    17.     {
    18.  
    19.         yield return new WaitForSeconds(5.0f);
    20.         Instantiate(fire,spawn.transform.position , spawn.transform.rotation);
    21.     }
    22.  
    23.  
    24. }
     
  2. Tiki

    Tiki

    Joined:
    Mar 3, 2013
    Posts:
    299
    I'd put the yield after the instantiate to prevent a delay the player might think is lag, also don't forget it's "StartCoroutine(DoStuff());" if you want to start an enumerator with a yield return.. otherwise I'd say you're on the right track, set the waitforseconds to 2.0f and it should instantiate one every 2 seconds... theoretically. Unity CoRoutines can give some weird results
     
  3. Tezelian

    Tezelian

    Joined:
    Oct 22, 2013
    Posts:
    256
    Hey thanks a lot

    Code (csharp):
    1.  using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class bullet : MonoBehaviour {
    5.  
    6.     public Transform Bulletspawn;
    7.     public GameObject Bulletfire;
    8.  
    9.     void Update () {
    10.    
    11.         StartCoroutine(DoStuff());
    12.  
    13.     }
    14.  
    15.  
    16.     IEnumerator DoStuff()
    17.     {
    18.  
    19.         yield return new WaitForSeconds(2.0f);
    20.         Instantiate(Bulletfire ,Bulletspawn.transform.position , Bulletspawn.transform.rotation);
    21.  
    22.  
    23.     }
    24.  
    25.  
    26. }
    So now I have this it waits 2 seconds, fires once but then it starts to fire continuously again? do you know why this is happening? How can I prevent this?
     
  4. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    Your coroutine will only execute once, so if you are instantiating multiple bullets after the 2 second wait, you have another script somewhere which is doing it.

    If you want your routine to loop,

    Code (csharp):
    1.  
    2. IEnumerator DoStuff()
    3. {
    4.   while(enabled)//Or some other condition that will be true until you don't need it
    5.   {
    6.  
    7.                 yield return new WaitForSeconds(2.0f);
    8.         Instantiate(Bulletfire ,Bulletspawn.transform.position , Bulletspawn.transform.rotation);
    9.      yield return null;
    10.   }
    11. }
    12.  
     
  5. Tiki

    Tiki

    Joined:
    Mar 3, 2013
    Posts:
    299
    There's got to be a better way to handle this than coroutines though, right? Maybe a clock reference to track time and instantiate every two seconds? I just don't like a 2 second script pause, personal thing I guess?
     
  6. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    Coroutines are a terrible way to solve this. You just record Time.time to a variable when you fire, then compare the current time to the variable and if more than two seconds have passed you fire and record the time.
     
  7. TheMeanCoder

    TheMeanCoder

    Joined:
    Apr 25, 2014
    Posts:
    15
    You could always use InvokeRepeating...

    Code (csharp):
    1.  
    2.      using UnityEngine;
    3.     using System.Collections;
    4.      
    5.     public class bullet : MonoBehaviour {
    6.      
    7.         public Transform Bulletspawn;
    8.         public GameObject Bulletfire;
    9.      
    10.         void Start () {
    11.        
    12.             InvokeRepeating("FireBullets", 0, 2.0f); //Fire a bullet every 2 seconds starting immediately
    13.      
    14.         }
    15.      
    16.        void FireBullets()
    17.         {
    18.             Instantiate(Bulletfire ,Bulletspawn.transform.position , Bulletspawn.transform.rotation);
    19.         }
    20.     }
     
  8. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I don't really know why people obsess over coroutines when

    shootTime -= Time.deltaTime;
    if (shootTime<0)
    {
    Fire();
    shootTime = 2;
    }

    Is simpler, and takes up the same amount of computation time, possibly less in some cases.

    Sometimes, it's better to just have the basics, bread and butter stuff. Only resort to coroutines where it actually would improve the code or be the right tool for the job.

    You could have a thousand of those and it wouldn't dent the profiler. I would use coroutines if I had to handle something more complicated though.
     
  9. CasaNu

    CasaNu

    Joined:
    Dec 21, 2021
    Posts:
    15
    You might want to use code tags while posting code: https://forum.unity.com/threads/using-code-tags-properly.143875/
     
  10. TheNullReference

    TheNullReference

    Joined:
    Nov 30, 2018
    Posts:
    222
    The reason this fires continuously is because every update you're starting a new coroutine. So this has the same effect as Update() just being delayed by 2 seconds.

    Your options are to use a boolean to check if a coroutine is already running, to use a timer in the update loop, use InvokeRepeating, or use async await.

    Here's a potential option:

    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3.  
    4. public class BulletSpawner : MonoBehaviour
    5. {
    6.     public GameObject bulletPrefab;
    7.     public float fireRate = 2f;
    8.     public bool isFiring = true;
    9.  
    10.     private void Start()
    11.     {
    12.         StartCoroutine(FireBullets());
    13.     }
    14.  
    15.     private IEnumerator FireBullets()
    16.     {
    17.         while (isFiring)
    18.         {
    19.             FireBullet();
    20.             yield return new WaitForSeconds(fireRate);
    21.         }
    22.     }
    23.  
    24.     private void FireBullet()
    25.     {
    26.         // Instantiate and set up the bullet here
    27.         GameObject bullet = Instantiate(bulletPrefab, transform.position, transform.rotation);
    28.     }
    29. }
    30.  
    You might be inclined to use Async

    Code (CSharp):
    1. using System.Threading.Tasks;
    2. using UnityEngine;
    3.  
    4. public class BulletSpawner : MonoBehaviour
    5. {
    6.     public GameObject bulletPrefab;
    7.     public float fireRate = 2f;
    8.     public bool isFiring = true;
    9.  
    10.     private async void Start()
    11.     {
    12.         while (isFiring )
    13.         {
    14.             FireBullet();
    15.             await Task.Delay((int)(fireRate * 1000)); // Convert fireRate to milliseconds
    16.         }
    17.     }
    18.  
    19.     private void FireBullet()
    20.     {
    21.         // Instantiate and set up the bullet here
    22.         GameObject bullet = Instantiate(bulletPrefab, transform.position, transform.rotation);
    23.     }
    24. }
    25.  
    Timer is also a good option. Timer versus Async will have slightly different side effects. Time will stop firing immediately, while async will fire one last bullet then stop. It may not make a big impact to your game but something to consider.
     
    arkano22 likes this.
  11. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,726
    MelvMay and TheNullReference like this.
  12. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    8,952
    MelvMay and spiney199 like this.
Thread Status:
Not open for further replies.