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:

http://unity3d.com/support/documentation/ScriptReference/MonoBehaviour.StartCoroutine.html?from=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?

http://unity3d.com/support/documentation/ScriptReference/MonoBehaviour.Update.html

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

2 Likes

No, just once per frame.

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

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". :) (You can make Start return an IEnumerator; you don't have to start a coroutine.)

--Eric

8 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: http://druss.co/2015/05/unity3d-waitforframes-in-coroutine/

5 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.

7 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? https://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html

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] [spoiler][/spoiler]

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