Search Unity

How to wait for a frame in c#?

Discussion in 'Scripting' started by Viskag, Jun 9, 2009.

  1. Viskag

    Viskag

    Joined:
    Apr 20, 2009
    Posts:
    46
    in java:
    functionABC()
    {
    ...;
    yield;
    ...;
    }
    how to wait for "just a frame" in c#?
    thx
     
    hopetolive and elektrofobi like this.
  2. DigitalGlass

    DigitalGlass

    Joined:
    May 12, 2009
    Posts:
    88
  3. DrHotbunz

    DrHotbunz

    Joined:
    Feb 14, 2009
    Posts:
    315
    or another way:
    var i : int = 0;

    function update () {

    i=i+1;

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

    }
     
  4. Tempest

    Tempest

    Joined:
    Dec 10, 2008
    Posts:
    1,286
    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.
     
  5. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    emris16 and ceitel like this.
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    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". :) (You can make Start return an IEnumerator; you don't have to start a coroutine.)

    --Eric
     
  7. Viskag

    Viskag

    Joined:
    Apr 20, 2009
    Posts:
    46
  8. Tempest

    Tempest

    Joined:
    Dec 10, 2008
    Posts:
    1,286
    My bad, ignore late night advice.

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

    drussilla

    Joined:
    Mar 20, 2014
    Posts:
    9
    Here is small class to wait for some amount of frames:
    Code (CSharp):
    1. public static class WaitFor
    2. {
    3.     public static IEnumerator Frames(int frameCount)
    4.     {
    5.         while (frameCount > 0)
    6.         {
    7.             frameCount--;
    8.             yield return null;
    9.         }
    10.     }
    11. }
    Here is how you can use it:
    Code (CSharp):
    1. public IEnumerator CoroutineAction()
    2. {
    3.     // do some actions here  
    4.     yield return StartCoroutine(WaitFor.Frames(5)); // wait for 5 frames
    5.     // do some actions after 5 frames
    6. }
    Found this class here: http://druss.co/2015/05/unity3d-waitforframes-in-coroutine/
     
    mhmtbtn, larry2013z, Stardog and 2 others like this.
  10. Rarceth

    Rarceth

    Joined:
    Oct 15, 2015
    Posts:
    41
    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!
     
  11. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    You don't actually have to do a StartCoroutine there, so it's even simpler:

    Code (csharp):
    1. public IEnumerator CoroutineAction()
    2. {
    3.     // do some actions here
    4.     yield return WaitFor.Frames(5); // wait for 5 frames
    5.     // do some actions after 5 frames
    6. }
    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.
     
    arcanevibe, Bunny83, LaKais and 4 others like this.
  12. Godfreyluck

    Godfreyluck

    Joined:
    Nov 4, 2018
    Posts:
    3
    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?
     
  13. WheresMommy

    WheresMommy

    Joined:
    Oct 4, 2012
    Posts:
    890
    wickedwaring likes this.
  14. humorkungen

    humorkungen

    Joined:
    Oct 29, 2019
    Posts:
    1
    Hi My i have a simple script!
    Code (CSharp):
    1. public float ABC;
    2. public float framesToWait;
    3. void Start{ABC = 0}
    4. void Update{ABC = ABC + 1;
    5. if (ABC > framesToWait}
     
    eaugustinowiczJC likes this.
  15. Tomasic212

    Tomasic212

    Joined:
    Dec 29, 2019
    Posts:
    2


    1. void Start()
    2. {
    3. StartCoroutine(ABC());
    4. }
    5. IEnumerator ABC()
    6. {

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

    9. //code goes here


    10. }


    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.
     
  16. Jorhoto

    Jorhoto

    Joined:
    May 7, 2019
    Posts:
    99
    You can also avoid something to be recalled the same frame:

    Code (CSharp):
    1. public struct OneTime
    2. {
    3.     private int _frameCount;
    4.  
    5.     /// <summary> Is first time called this frame? </summary>
    6.     public bool IsFirstTimeCalledThisFrame()
    7.     {
    8.         bool result = _frameCount != Time.frameCount;
    9.         _frameCount = Time.frameCount;
    10.      
    11.         return result;
    12.     }
    13. }
    Then in whatever you don't want to be called more than once in the same frame:
    Code (CSharp):
    1. // Field:
    2. private OneTime _oneTime;
    3.  
    4. ...
    5.  
    6. // Avoid recalling the same frame.
    7. if (!_oneTime.IsFirstTimeCalledThisFrame()) { return; }
     
    geck1942 likes this.
  17. Jorhoto

    Jorhoto

    Joined:
    May 7, 2019
    Posts:
    99
    To extend on my own answer, looks like after Unity 2018 we got: await Task.Yield()

    Tested example:
    Code (CSharp):
    1.     private async void TryNextFrame()
    2.     {
    3.         Debug.Log($"{Time.frameCount} Current frame.");
    4.         await Task.Yield();
    5.         Debug.Log($"{Time.frameCount} This log will appear next frame...");
    6.     }
    7.  
     
    kustom likes this.
  18. anszwa

    anszwa

    Joined:
    Jul 30, 2012
    Posts:
    42
    Not the best solution, and coroutines are definitely cleaner, but sometimes that's handy:
    Code (CSharp):
    1. bool waitForOneFrame = true;
    2.  
    3. private void Update()
    4. {
    5.     if (waitForOneFrame)
    6.     {
    7.         waitForOneFrame = false;
    8.     }
    9.     else
    10.     {
    11.         // your code
    12.     }
    13. }
     
    Wilhelm_LAS likes this.