-1

I want to wait .01 second for every iteration of a for loop, but I can't figure out why.

heres the plain code with no wait.

public void BlackOut()
    {
        for (int i = 1; 1<255; i++)
        {
            Color tmp = gameObject.GetComponent<SpriteRenderer>().color;
            tmp.a = i;
            gameObject.GetComponent<SpriteRenderer>().color = tmp;

            //Wait here
        }   

    }

I want to add the wait at the at the comment but everything I tried doesn't work

In lua it is :

for i = 1,255 do
    --change color depending on engine
    wait(.01)
end

I tried wait for seconds, task.delay, ect..

Sjdinsd
  • 1
  • 1
  • 1
    Note: your for loop is infinite because of a typo. You want `i < 255` not `1 < 255` – Petrusion May 01 '23 at 10:18
  • Does this answer your question? [How to make the script wait/sleep in a simple way in unity](https://stackoverflow.com/questions/30056471/how-to-make-the-script-wait-sleep-in-a-simple-way-in-unity) – Jay May 01 '23 at 13:57

4 Answers4

3

The simplest solution would be to adapt your existing code as a coroutine.

  1. Make BlackOut a Coroutine by changing void to IEnumerator
  2. Use yield return new WaitForSeconds(0.01f); at your //Wait here comment
  3. 'Call' the BlackOut coroutine using StartCoroutine(BlackOut());
public IEnumerator BlackOut()
{
    for (int i = 1; i<255; i++)
    {
        Color tmp = gameObject.GetComponent<SpriteRenderer>().color;
        tmp.a = i;
        gameObject.GetComponent<SpriteRenderer>().color = tmp;

        //Wait here
        yield return new WaitForSeconds(0.01f);
    }   
}

// How to run the coroutine
void SomeOtherMethod()
{
    StartCoroutine(BlackOut());
}

Note: I have made no attempt to address any frame rate dependence introduced by using WaitForSeconds this way. My answer only addresses the question of how to wait some time within a for loop. If you need this code to be frame-rate independant then you will need to scale the rate of change with a delta time value, and you might want to yield return null instead to ensure the coroutine runs every frame.

0

As rshepp answered, it is true that it is a good idea to do this in a coroutine, but I advise against waiting in a loop.

If you write the coroutine like that, you will tie it to fps. Between each yield return WaitForSeconds(...) at least one frame needs to happen. So on slow framerate making the object visible is going to be slower than on high framerates. Furthermore, on high framerates the appearing of the object wouldn't be as smooth as it could be.

Instead use an approach that works with any framerate (fast or slow):

public IEnumerator BlackOut()
{
    const float fadeTimeSeconds = 2.5f;

    float startTime = Time.time;
    float currentTime = startTime;
    float stopTime = startTime + fadeTimeSeconds;

    var spriteRenderer = gameObject.GetComponent<SpriteRenderer>();

    while (currentTime <= stopTime)
    {
        currentTime = Time.time;

        var color = spriteRenderer.color;
        
        // currentTime-startTime is the time elapsed since the coroutine started
        // divide it by the fade time to get a value between 0 and 1
        // (we know it is between 0 and 1 because currentTime is between startTime and stopTime)
        color.a = (currentTime - startTime) / fadeTimeSeconds;
        spriteRenderer.color = color;

        // this makes the coroutine wait until next frame
        yield return null;
    }
    
    // make sure the fade is complete
    // without this code the fade could stop at for example 99% opacity
    var finalColor = spriteRenderer.color;
    finalColor.a = 1;
    spriteRenderer.color = finalColor;
}
Petrusion
  • 940
  • 4
  • 11
0

Well you could adopt async, which I use rather than coroutines nowadays.

async Task MyFunction()
{
    await BlackOut();
}


public async Task BlackOut()
    {
    for (int i = 1; 1 < 255; i++)
    {
        Color tmp = gameObject.GetComponent<SpriteRenderer>().color;
        tmp.a = i;
        gameObject.GetComponent<SpriteRenderer>().color = tmp;

        //Wait here
        await Task.Delay(10); // Paus 0.01 second
    }
}

Here is a very good tutorial comparing async and coroutines if you are not familiar with async: https://www.youtube.com/watch?v=WY-mk-ZGAq8

PeterK
  • 4,243
  • 4
  • 44
  • 74
0

Here is an approach without coroutines: Instead of waiting and changing the value, you could also fade the color in a framerate-independent way like this:

float timer = 0;
bool blacking_out = false;
SpriteRenderer spriteRenderer;

public void BlackOut()
{
    blacking_out = true;
}

void Start()
{
    spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
}

void Update()
{
    if(blacking_out)
    {
        timer += Time.deltaTime;
        timer = Mathf.Clamp01(timer);
        if(timer == 1f)
        {
            blacking_out = false;
        }
        // change color alpha over time. 
        Color tmp = spriteRenderer.color;
        tmp.a = timer * 255;
        spriteRenderer.color = tmp;
    }
}
KYL3R
  • 3,877
  • 1
  • 12
  • 26