Set WaitForSeconds() to zero still make Instantiate delay?

Hi, I have a problem about WaitForSeconds when editor set zero delay. It is not the result I was expecting, even set to zero, it’s like the instantiate of object delay maybe about 0.02 seconds? Can someone help me with a solution?

Here’s the snapshot (some code parts and result) I was actually working: (Image – left: without delay; right: with WaitForSeconds() set to zero)

But let’s just go here; here’s my simplified testing script:
CoroutineTest.cs

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

public class CoroutineTest : MonoBehaviour {

    public Transform spawnPoint;
    public float rotationOffset;
    private float _rotationOffset;
    public int shootAmount = 0;
    [Range(0,1)] public float shootDelay = 0f;
 
    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown (KeyCode.Space))
            StartCoroutine (Test1 (1));
        if (Input.GetKeyDown (KeyCode.E))
            StopCoroutine (Test1 (2));
    }

    IEnumerator Test1 (int code) {
        float setRotation = _rotationOffset;
        if (code == 1)
        {
            _rotationOffset += rotationOffset;
            for (int i = 0; i < shootAmount; i++) {
                Instantiate (spawnPoint, transform.position, transform.rotation * Quaternion.Euler (0f, setRotation, 0f));
                //work expected: 0.1f, 0.2f, 1, 2, 2.5f except 0 (zero)...
                yield return new WaitForSeconds (shootDelay);
                //yield return new WaitForSeconds (0);
            }
        }
        else
        {
            Debug.Log ("Stop CoRoutine!");
        }
        yield return null;
    }
}


I attach a zip file for this ^ StartCoroutineTesting.zip

Thank you so much, your help is appreciated!



3171859–241636–StartCoroutineTesting.zip (625 KB)

I assume this is the code with issue? and by issue I mean, there is no pause between each shootAmount. so this is like 6 shoots in a gun. and you are trying to build a cool down system to delay how often the player can shoot his gun.

  • for (int i = 0; i < shootAmount; i++) {
  • Instantiate (spawnPoint, transform.position, transform.rotation * Quaternion.Euler (0f, setRotation, 0f));
  • //work expected: 0.1f, 0.2f, 1, 2, 2.5f except 0 (zero)…
  • yield return new WaitForSeconds (shootDelay);
  • //yield return new WaitForSeconds (0);
  • }

the issue is really in the Update(), the spacebar is creating multiple instances of the Coroutine. and there for the player can shoot when ever he wants. you might have 20 or 50 coroutines running at the same time.

try a bool to stop the player from pressing the space bar

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
public class CoroutineTest : MonoBehaviour {
 
    public Transform spawnPoint;
    public float rotationOffset;
    private float _rotationOffset;
    public int shootAmount = 0;
    [Range(0,1)] public float shootDelay = 0f;
    private bool cooldown = false;
 
    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown (KeyCode.Space) && cooldown == false)
            StartCoroutine (Test1 (1));
        if (Input.GetKeyDown (KeyCode.E))
            StopCoroutine (Test1 (2));
    }
 
    IEnumerator Test1 (int code) {
        float setRotation = _rotationOffset;
        if (code == 1)
        {
          cooldown = true;
            _rotationOffset += rotationOffset;
            for (int i = 0; i < shootAmount; i++) {
                Instantiate (spawnPoint, transform.position, transform.rotation * Quaternion.Euler (0f, setRotation, 0f));
                //work expected: 0.1f, 0.2f, 1, 2, 2.5f except 0 (zero)...
                yield return new WaitForSeconds (shootDelay);
                //yield return new WaitForSeconds (0);
            }
          cooldown = false;
        }
        else
        {
            Debug.Log ("Stop CoRoutine!");
        }
        yield return null;
    }
}

That’s also not how you use StopCoroutine (that whole thing looks goofy).

StartCoroutine gives you back the Coroutine you started so you can skip the bool and just check if one is already working

Coroutine shoot;

void Update()
{
    if (Input.GetKeyDown(...) && shoot == null)
    {
        shoot = StartCoroutine(Test());
    }
    else if (Input.GetKeyDown(...) && shoot != null)
    {
        StopCoroutine(shoot);
        shoot = null;
    }
}
1 Like

Hi, thank you for the reply… but sorry for the lack of detail what I really want to achieved; I only concern is that WaitForSeconds() can’t go below 0.02 seconds, is that right? I use WaitForSeconds(), not for player, but for enemy/AI trigger to do hell bullet patterns or with style: for example
https://www.youtube.com/results?search_query=game+hell+bullet

I want an option for to shoot parallel bullets with or without delay, I once use WaitForSeconds() for spawning enemies with gaps or instantly spawn all at once (WaitForSeconds(spawnGap) as spawnGap = 0), or they just seem to be but not… not until I make this HellBulletManager.cs:



In short, my only concern is that WaitForSeconds() can’t go instant? There will always be at least 0.02 seconds delay?
If that’s the case, can’t be done; I’ll just have to do the cheap way solution like:

if (linearDelay > 0)
    yield return new WaitForSeconds(linearDelay);

What do you think, guys? ^

P.S. Thank you, now I know how to use StopCoroutine(); :smile: not using to my actual script HellBulletManager.cs, I just trying it to my testing script…


Unity’s documentation is a little vague here:

So, my interpretation of that is even if the value is 0, it still waits for at least one frame.

So yes, doing an if check first seems like the way to go if you want to immediately continue if the value is 0.

3 Likes

How do i make a delay in milliseconds? - Questions & Answers - Unity Discussions has a discussion on this (the first google for “unity waitforseconds milliseconds,” if you were curious.) It expands on the line BP quotes, about counting frames.

Yup, bingo. Just tested it.


using System.Collections;
using UnityEngine;

public class WaitForSecondsTest : MonoBehaviour
{
public float WaitTime;
private float TimeStamp;

void Start() => StartCoroutine(Wait());

private IEnumerator Wait()
{
TimeStamp = Time.time;

for (int i = 1; i <= 1000; i++)
{
yield return new WaitForSeconds(WaitTime);
Debug.Log((Time.time - TimeStamp).ToString() + " has passed");
}
}
}