0
\$\begingroup\$

I am currently programming a custom programming language and using Unity to run it. My current issue is that while loops freeze the game when their done. Is there a simple way to wait until end of frame in unity or wait for time?

\$\endgroup\$
1
  • \$\begingroup\$ Sounds like you want a Coroutine. Try implementing your solution based on the documentation there, and if you have trouble applying it to your case, edit your question to show us more details of where you need help. \$\endgroup\$
    – DMGregory
    Nov 18 '21 at 18:03
2
\$\begingroup\$

Instead of using a while loop in Unity, you need to use a Coroutine. To demonstrate how to do this, I will show you what you would normally do, and then show how a coroutine is different.

Traditional While Loop Structure

void Loop()
{
    while(running)
    {
        // Do stuff here
    }
}

Unity Coroutine Structure

IEnumerator Loop()
{
    while(condition)
    {
        // Do stuff here
        yield return null;
    }
}

Example

The following code fades text continuously.

using UnityEngine;
using UnityEngine.UI;
using System.Collections;


public class Transitions : MonoBehaviour
{
    Coroutine fade = null;
    public Text text;
    public float speed = 1;
    void Update()
    {
        if(fade == null)
            fade = StartCoroutine(Fade());
    }

    public IEnumerator Fade()
    {
        Color c = text.color;
        Color target = Color.clear;
        float a = text.color.a;
        while(a > 0)
        {
            a -= speed * Time.deltaTime;
            text.color = new Color(c.r, c.g, c.b, a);
            yield return null;
        }
        text.color = Color.clear;
        while(a < 1)
        {
            a += speed * Time.deltaTime;
            text.color = new Color(c.r, c.g, c.b, a);
            yield return null;
        }
        text.color = c;
        fade = null;
    }
}

Explanation

(What this does line by line)

  1. When we call StartCoroutine(Fade());, we assign it to the fade Coroutine variable. This variable holds a pointer to the coroutine.
  2. When fade completes, we assign it to null to ensure it can be used again.
  3. Now that fade is null, the update loop will execute a new iteration of the the Fade() Coroutine.

Credit goes to @DMGregory for correcting my use of bool locks and providing the explanation above.

Valuable Tips

We can break out of the Coroutine using yield break;

If you do not yield return null inside the loop, the coroutine does not return between frames and will wait for the loop to end as in a normal while loop.

We can break out of the while loop in the Coroutine, by using break as per normal.

Links

For more information regarding the proper implementation and use of coroutines:

\$\endgroup\$
2
  • \$\begingroup\$ Feel free to edit the answer any way you see fit if it will benefit future users. Cheers. \$\endgroup\$
    – Triangle4
    Jan 24 at 22:34
  • \$\begingroup\$ I'm glad I could be of use here. It might be worth mentioning in your answer why checking before starting the coroutine is advantageous (for avoiding GC allocation), just in case it strikes a reader as unnecessarily complex compared to the bool method you'd shown previously. \$\endgroup\$
    – DMGregory
    Jan 24 at 22:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .