Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question [UnityTest] requires hundreds of "yield return null" to advance one frame. Bug?

Discussion in 'Testing & Automation' started by CodeSmile, May 22, 2023.

  1. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,533
    In [UnityTest] it is said that "yield return null" skips one frame. However this is not what I'm seeing (in 2023.1 beta). I have a simple test:
    Code (CSharp):
    1. [UnityTest] public IEnumerator SimpleFrameCountTest()
    2.        {
    3.            int yieldCount = 0;
    4.            var renderedFrameCount = Time.renderedFrameCount;
    5.            var currentFrameCount = Time.frameCount;
    6.            while (currentFrameCount == Time.frameCount)
    7.            {
    8.                yieldCount++;
    9.                yield return null;
    10.            }
    11.  
    12.            Debug.Log($"Wait 1 frameCount required {yieldCount} yields " +
    13.                      $"over {Time.renderedFrameCount - renderedFrameCount} frames");
    14.        }
    And it logs this:
    Wait 1 frameCount required 360 yields over 1 frames

    Meaning it takes 360 yields to advance both Time.frameCount AND Time.renderedFrameCount by one. The number of yields varies, and they are extremely high (like 10,000 or more) if I do the same in a IEditModeTestYieldInstruction class in the Perform() method.

    Is this expected or a bug or an issue on my part?

    I have a hunch that this is only true in PlayMode whereas in EditMode tests the frame updates are slowed down a lot. Although I did set the editor to "No Throttling".
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,533
    Of course the functionality works as expected in PlayMode, even though it specifically says under the Edit Mode documentation that it will "skip the current frame".
     
  3. sbergen

    sbergen

    Joined:
    Jan 12, 2015
    Posts:
    53
    What exactly are you expecting to do with information about "frames" in Edit Mode tests? None of the stuff that normally happens during a game frame is guaranteed to happen in Edit Mode tests (e.g. calls to Update methods), so I personally find the concept of a "frame" in an Edit Mode test to be pretty ill-defined, or at least misleading terminology. The documentation you linked also contains this description of the differences:

    ... the next iteration of either the EditorApplication.update loop or the game loop. ​

    So if we are pedantic, "skip the current frame" actually means "proceed to the next iteration of the EditorApplication.update loop". There will (normally) be no game frames rendered in Edit Mode tests, and there may or may not be an Editor frame rendered, as you have observed.

    If you are testing some Editor code, things generally get more complicated, so I think you'd be better off asking about the specific thing you are trying to test, instead of asking about frame counts.
     
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,533
    It also says just under the Edit Mode test heading:
    A frame is a frame is a frame, I would say. Even though EditorApplication.update fires differently than runtime, if the test docs state that yielding does "skip the current frame" I do expect it to do skip to the **next** frame, meaning it should advance Time.frameCount accordingly - otherwise it isn't actually skipping the **current** frame, right?

    In fact, the EditorApplication.update does render the same frame (according to frameCount) repeatedly. That's an intricate detail that isn't immediately obvious by mentioning EditorApplication.update once in the opening paragraph. It should in fact read "continues with the next EditorApplication.update event", not frame.

    My thought was simply to quickly test a coroutine that used Time.frameCount in an edit mode test. I tend to test as much as possible in edit mode rather than playmode because its faster, but that's just one of the things that requires a runtime test.
     
  5. sbergen

    sbergen

    Joined:
    Jan 12, 2015
    Posts:
    53
    I think we both agree that the documentation is confusing, and I'm trying to further state that the term "frame" should probably not be used at all while talking about Edit Mode tests.

    The reason I'm saying a lot of "frame" is ill-defined in Edit Mode tests is exemplified by the documentation of
    Time.frameCount

    The total number of frames since the start of the game (Read Only).
    This value starts at 0 and increases by 1 on each Update phase.​

    The game is not started, and there aren't any (normal) Update phases in Edit Mode tests, so I would actually expect it to be e.g. -1 when in Edit Mode tests.