Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

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,204
    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.
     
  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:
    39
    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. }