Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
37
Question by Siflou · Jul 23, 2014 at 10:18 PM · coroutineyield

yield return null vs yield return WaitForEndOfFrame

Hey guys, I wonder what is the difference between yield return null and yield return new WaitForEndOfFrame(). For example if i used this in a coroutine like that.

 IEnumerator MyRoutine()
 {
 yield return new WaitForEndOfFrame();
 Debug.Log("Hello");
 }
 
 IEnumerator MyRoutine2()
 {
 yield return null;
 Debug.Log("Hi");
 }

I think that it should produce the same result right ? Does anyone have an idea ?

Thanks a lot !

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
73
Best Answer

Answer by rutter · Jul 23, 2014 at 10:43 PM

They're very similar, but return at different points in the frame.

Unity performs many operations once per frame, including:

  • Input processing

  • Main update (including Update())

  • Main coroutine updates (including yield return null)

  • Late update (including LateUpdate())

  • Scene rendering (quite a few steps)

  • Gizmo/UI rendering

  • End of frame (including WaitForEndOfFrame)

One returns just before rendering, the other returns just after (but just before the frame is displayed). When the difference isn't important, I usually use and recommend yield return null, as it's closer to the way other Update and coroutine functions work.

This is explained in more detail at the execution order manual page. Recently, they've added a handy chart:

Execution order


order.png (86.7 kB)
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image fafase · Jan 20, 2015 at 01:53 PM 0
Share

Does anyone have any idea on memory management about this issue?

yield return null; seems to be a simple command while yield return null WaitForEndOfFrame as the new keyword and WaitForEndOfFrame is an actual class

So I would suspect it to create an object like a subsidiary coroutine to the existing coroutine. Is that so?

avatar image Bunny83 · Apr 15, 2015 at 11:51 AM 4
Share

@fafase:
WaitForEndOfFrame is, like you said, just a class. Actually it's an empty class. It's declared as:

 public sealed class WaitForEndOfFrame : YieldInstruction
 {
     
 }

YieldInstruction is also just an empty class (they could have used an interface for that):

 public class YieldInstruction
 {
     
 }

So the only thing the coroutine scheduler actually use from that class is the type of the object. Of course every class instance need at least 1 byte of memory that can be addressed. Usually with a 4 byte alignment an instance uses 4 bytes. However i haven't tested it yet. Could be more and could be different depending on the target platform.

edit It seems to be 8 bytes according to this SO answer

WaitForSeconds is also just an ordinary class, but it holds additional information for the scheduler:

 public sealed class WaitForSeconds : YieldInstruction
 {
     internal float m_Seconds;
     public WaitForSeconds(float seconds)
     {
         this.m_Seconds = seconds;
     }
 }

The internal value is used by the scheduler to deter$$anonymous$$e when it has to schedule this coroutine again.

So since WaitForEndOfFrame as well as WaitForFixedUpdate are just empty classes it should probably be no problem to actually cache a single instance of that class and pass that one to yield return whenever you need it.

A helper class like this might work:

 public static class Wait
 {
     private static WaitForEndOfFrame m_WaitForEndOfFrame = new WaitForEndOfFrame();
     private static WaitForFixedUpdate m_WaitForFixedUpdate = new WaitForFixedUpdate();
     public static WaitForEndOfFrame ForEndOfFrame
     {
         get {return m_WaitForEndOfFrame;}
     }
     public static WaitForFixedUpdate ForFixedUpdate
     {
         get {return m_WaitForFixedUpdate;}
     }
 }

Use it like this:

 IEnumerator SomeCoroutine()
 {
     // SomeStuff
     yield return Wait.ForEndOfFrame;
     // Some more stuff
 }

This would prevent the creation of a new instance each time you need one of those classes. It's of course possible that Unity has some additional overhead in the scheduler itself. But we can't do anything about that ^^.

avatar image
5

Answer by Bunny83 · Jul 23, 2014 at 10:46 PM

Of course both of your examples will execute the Debug.Log line, however at different times. If you yield "null" (or any other value that isn't recognised) Unity will schedule this coroutine the next frame right after Update is called. When you use WaitForEndOfFrame, The coroutine will be scheduled this frame once all cameras are rendered and the GUI is drawn. It will run right before the buffers are swapped and the frame is finished.

See this great Unity Gems article for more information

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Siflou · Jul 24, 2014 at 11:20 AM 0
Share

Thanks a lot :)

avatar image ForceMagic · Apr 13, 2015 at 08:20 PM 0
Share

too bad, the website seems to be down by now, I only managed to access it with an Archive : https://web.archive.org/web/20140626101041/http://unitygems.com/

avatar image fredsa ForceMagic · Mar 28, 2017 at 04:07 PM 1
Share

Looks like the site has a new domain name, the article is now at https://unitygem.wordpress.com/coroutines/

avatar image
0

Answer by unity_123uzunince123 · Nov 11, 2020 at 09:24 PM

This article is a bit old, maybe at that times the system worked different. But I've made an experiment resulting different from you have talked. here is the code:

 using System.Collections;
 using UnityEngine;
 using UnityEngine.EventSystems;

 public class CizgiCizKaydet : EventTrigger
 {
 
     public static bool allow = false;
     
     public override void OnEndDrag(PointerEventData eventData)
     {
         StartCoroutine(AllowPrintForOneFrame());
     }
     IEnumerator AllowPrintForOneFrame()
     {
         allow = true;
         yield return new WaitForEndOfFrame();
         // yield return null;
         allow = false;
     }
     private void Update()
     {
         if (allow )
             print("Merhaba");
     }
 }
   

for the "yield return null;" version the print("Merhaba"); is executed twice. for the "yield return new WaitForEndOfFrame();" version print("Merhaba"); is executed once.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image unity_987gLU_QOEEZWg · Nov 21, 2020 at 02:01 PM 0
Share

I've the same problem and asked it on stackoverflow, nobody seems to have any answer for that https://stackoverflow.com/questions/64942789/waitforendofframe-is-called-twice-at-first-run

avatar image Bunny83 unity_987gLU_QOEEZWg · Nov 21, 2020 at 02:23 PM 1
Share

This is most likely not the same issue. As derHugo has explained on your SO question, the very first frame in Unity has several edge cases. That's also true for the value of deltaTime and a few other things. So you should not rely on that.


And no, your second debug log is not some how called twice. You just have two coroutines waiting for the "end of frame" which somehow does not happen at the very first frame. So your first coroutine simply completes together with your second one at the end of frame 2. That's exactly what you're seeing. As others have suggested, pass the frame count as a parameter to your coroutine so it actually stays the same, even though the coroutine lasts longer than one frame. Then you will see that one of the two "4" debug logs comes from frame 1 and the other from frame 2. Time.frameCount returns the frame at the point it's called. Since both coroutines finish at frame 2, of course both show a frameCount of 2. However that's not the frame it was actually started.


In this case here he actually reacts to the "OnEndDrag" event. So this does not happen at the first frame. The most likely reason why he sees the message two times is because he probably has attached the script to two gameobjects. Since his "allow" variable is static it will of course affect both scripts, even though only one of them may receive the event.

avatar image
0

Answer by NogeGames · May 17 at 08:27 AM

The best answer is wrong.

  • When you yield return WaitForEndOfFrame the coroutine will be resumed at the end of the current frame, after scene and ui rendering.

  • When you yield return null the coroutine will be resumed in the next frame right after the Update is completed.

WaitForEndOfFrame is useful when you want the coroutine to be resumed later this frame, while returning null will resume it after next frame's Update, which is a very important difference sometimes.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

32 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Unityscript Coroutine Not Running When Called 1 Answer

Null Reference Exception after updating from 4.0 to 4.1.5 (coroutines) 0 Answers

Question about WaitForFixedUpdate() 1 Answer

Coroutoutine doesnt work properly. 3 Answers

Getting an error when trying to yield 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges