WaitForEndOfFrame is called twice at first run
Asked Answered
F

1

0

I'm trying to understand WaitForEndOfFrame and almost figured, but the problem is when the first yield is encountered, it skips and save it for the next frame, and in the next frame it is resumed at the end of the rendering, but it's called twice, and it continues to work as expected for the rest of the frames. can't find out why the expected code after yield is called twice in the second frame.

void Update()
{
    print("1 - " + Time.frameCount);
    StartCoroutine(Enu());
    print("3 - " + Time.frameCount);
}

IEnumerator Enu()
{
    print("2 - " + Time.frameCount);
    yield return new WaitForEndOfFrame();
    print("4 - " + Time.frameCount);
}

1 - 1

2 - 1

3 - 1

--

1 - 2

2 - 2

3 - 2

4 - 2

4 - 2 <-- ?

--

1 - 3

2 - 3

3 - 3

4 - 3

--

1 - 4

2 - 4

3 - 4

4 - 4

--

1 - 5

2 - 5

3 - 5

4 - 5

Footplate answered 21/11, 2020 at 12:0 Comment(7)
No it is not really called twice ... One of them is the delayed one from the very first frame where it wasn't printed yet .. not 100% sure but it seems that the very first frame gets delayed to the next one .. seems to be an edge caseRadiosurgery
yes, all of them are delayed from previous frame, but the delayed one from the first frame is called twice, you can test it out. this guy from the last answer has the same problem answers.unity.com/questions/755196/…Footplate
I don't think they are all delayed one frame.. only the first one is continued in the second frame where frameCount is already 2 ... You could check that out better by passing the frameCount as parameter into your routine and let it print the parameter in order to see for which frame it got continued .. currently on my phone so can't test it myselfRadiosurgery
the frameCount is printed as the second number in the list result shown above, as u can see the frameCount 2 is printed twice for the number 4, which is the delayed code from first frame, so when its at frame 2, the print("4 - " + Time.frameCount); is called twiceFootplate
Checkout this post (The second from the bottom from Dantus) they experienced exactly your issue, they just tested it as I said by passing in the frameCount as parameter in order to have the same one within the same routine. The first frame gets delayed into the second one.. after that it works as expected. They also expected it to be a bug .. apparently one that was never fixed ;)Radiosurgery
so it's a bug, if you use yield return null; the problem resolves. thank you for helping btw @RadiosurgeryFootplate
Note that this is not really true neither ;) If you use yield return null; you continue the routine at a complete different moment and actually delay them all into the next frame (after all Update calls of the next frame are done). It doesn't replace WaitForEndOfFrame which is e.g. quite essential for anything you want to do right after all calculations but before the frame gets rendered (e.g. enable/disable something, after effects etc)Radiosurgery
R
2

I would say it is not called twice but what happens is rather that the very first Coroutine started in the first frame is continued until within the second frame where the frameCount is already 2.


This seems to be a Unity BUG related to WaitForEndOfFrame and the very first frame of the application!

See e.g. this post (The second from the bottom from Dantus)

where they experienced exactly the same issue, just tested it a bit better by passing the current frameCount as parameter into the routine so they knew for which frame it was actually continued:

public class WaitForEndTest : MonoBehaviour 
{      
     private void Update ()
     {  
         Debug.Log ("Update: " + Time.frameCount);
         StartCoroutine (WaitForEndOfFrameCoroutine (Time.frameCount));
     }
 
     private IEnumerator WaitForEndOfFrameCoroutine (int frameCount) 
     {
         Debug.Log ("Before end of frame: " + frameCount);
         yield return new WaitForEndOfFrame ();
         Debug.Log ("After end of frame: " + frameCount);
     }
}

which also for them printed similar to your case

Update: 1
Before end of frame: 1
Update: 2
Before end of frame: 2
After end of frame: 1
After end of frame: 2

You should see it as a little hiccup of Unity during the initialization of your app and ignore it ;)

Radiosurgery answered 21/11, 2020 at 14:22 Comment(1)
Yes, this is most likely what's happening. The first frame has several oddities as a lot systems are warming up. You also get dodgy values for deltaTime. Though you usually wouldn't rely on them in the first frame. AFAIK the very first frame isn't even rendered properly. So the first frame should be seen as a warm up cycle.Mod

© 2022 - 2024 — McMap. All rights reserved.