How to wait for a frame in c#?

in java:
functionABC()
{
…;
yield;
…;
}
how to wait for “just a frame” in c#?
thx

2 Likes

What you want to do is start a coroutine:

So in your case

void Start()
{
 StartCoroutine(ABC());
}
IEnumerator ABC()
{

//returning 0 will make it wait 1 frame
 yield return 0;

//code goes here


}
18 Likes

or another way:
var i : int = 0;

function update () {

i=i+1;

if (i==2) {
print(“this message prints every second frame”);
i=0;
}

}

3 Likes

Update can run many times per frame, but it’s close.

You could try to set something up with FixedUpdate, which runs every frame, based on a set frame rate.

Are you sure about this? I thought Update() was defined to execute exactly once per frame. How else would this be accurate?

You sure you’re not thinking of OnGUI() ?

2 Likes

No, just once per frame.

Don’t use FixedUpdate for anything except physics code; that’s what it’s for.

Anyway, the correct answer to the original question is “yield return null”. :slight_smile: (You can make Start return an IEnumerator; you don’t have to start a coroutine.)

–Eric

10 Likes

thanks!

My bad, ignore late night advice.

Update runs many times per second,(many frames per second), and I got turned around.

Here is small class to wait for some amount of frames:

public static class WaitFor
{
    public static IEnumerator Frames(int frameCount)
    {
        while (frameCount > 0)
        {
            frameCount--;
            yield return null;
        }
    }
}

Here is how you can use it:

public IEnumerator CoroutineAction()
{
    // do some actions here   
    yield return StartCoroutine(WaitFor.Frames(5)); // wait for 5 frames
    // do some actions after 5 frames
}

Found this class here: [Unity3d] WaitForFrames in Coroutine

6 Likes

Absolutely reviving this thread to ask question about that last answer; When you ask for the return of the Coroutine “Frames”, it actually waits for the coroutine??? I had previously searched for a way to wait for coroutine to be finished and heard nothing useful!

You don’t actually have to do a StartCoroutine there, so it’s even simpler:

public IEnumerator CoroutineAction()
{
    // do some actions here 
    yield return WaitFor.Frames(5); // wait for 5 frames
    // do some actions after 5 frames
}

The rules are:

  • if you yield a YieldInstruction - like WaitForSeconds or a custom one - the coroutine waits until that returns false for
    keepWaiting
  • if you yield an IEnumerator or a StartCoroutine, you start that coroutine, and your current coroutine waits until the inner coroutine is done.
  • if you yield anything else, you wait a single frame.
8 Likes

Here’s a question, and possible solution to the original question.

If I use WaitForSeconds in an IEnumerator, and set the time to 0, will the coroutine start again next frame, or immediately?

For example:

IEnumerator ExampleCoroutine()
{
First();
yield return new WaitForSeconds(0);
Second();
}

Will Second() happen on the same frame as First(), or one frame later?

My two cents, what about that already present one? Unity - Scripting API: WaitForEndOfFrame

1 Like

Hi My i have a simple script!

public float ABC;
public float framesToWait;
void Start{ABC = 0}
void Update{ABC = ABC + 1;
if (ABC > framesToWait}

You Need to Have a consistant framerate.[/code]

1 Like
      • void Start()
  • {
  • StartCoroutine(ABC());
  • }
  • IEnumerator ABC()
  • {
    • //returning 0 will make it wait 1 frame
  • yield return 0;
    • //code goes here
      • }

so i used this script and it actually waited for one frame when i understood it…
but… even when i changed the yield return it kept on waiting only one frame
pls help me wait different amount of frames in this script. (i understand this script and i want to keep doing things i know instead of breaking my head trying to understand other scripts…) if u have any other SIMPLE scripts i might try them.

thx, Tom Markovich.

You can also avoid something to be recalled the same frame:

public struct OneTime
{
    private int _frameCount;

    /// <summary> Is first time called this frame? </summary>
    public bool IsFirstTimeCalledThisFrame()
    {
        bool result = _frameCount != Time.frameCount;
        _frameCount = Time.frameCount;
      
        return result;
    }
}

Then in whatever you don’t want to be called more than once in the same frame:

// Field:
private OneTime _oneTime;

...

// Avoid recalling the same frame.
if (!_oneTime.IsFirstTimeCalledThisFrame()) { return; }
1 Like

To extend on my own answer, looks like after Unity 2018 we got: await Task.Yield()

Tested example:

    private async void TryNextFrame()
    {
        Debug.Log($"{Time.frameCount} Current frame.");
        await Task.Yield();
        Debug.Log($"{Time.frameCount} This log will appear next frame...");
    }
2 Likes

Not the best solution, and coroutines are definitely cleaner, but sometimes that’s handy:

bool waitForOneFrame = true;

private void Update()
{
    if (waitForOneFrame)
    {
        waitForOneFrame = false;
    }
    else
    {
        // your code
    }
}
1 Like