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. Dismiss Notice

Resolved Subsequent frames not stopping?

Discussion in 'Editor & General Support' started by justin_kasowski, Nov 9, 2022.

  1. justin_kasowski

    justin_kasowski

    Joined:
    Jan 14, 2020
    Posts:
    45
    I'm not sure why this isn't working and was hoping someone could explain it to me.

    Basically, I have a Singleton. In that Singleton, I have a bool: "isLoading". Before starting a heavy calculation, I set
    isLoading = true;
    " and only after the calculations are done,
    isLoading=false;


    In another MonoBehavior, I have an Update function that's something to the effect of:

    Code (CSharp):
    1. if (Singleton.Instance.IsLoading){
    2.    DisplayLoadingScreen;
    3. else
    4.    DoOtherStuff;


    It displays the loading screen (a RawImage on Canvas) for about a half second then goes and starts doing the other stuff.

    I know the calculations aren't complete since the editor freezes for a good 5-10 seconds and I know the calculations take ~5-10 seconds. This is kind of driving me crazy. There are all these options for how to spread heavy calculations across frames with a coroutine, but nothing on how to just stop subsequent Update() calls until the current frame is done. That seems like it should be an easy thing to do and I'm hoping there's something simple that I'm just not finding.

    EDIT: In case anyone stumbles across this... Unity will not load a subsequent frame until calculations are complete (unless you use a coroutine and yield frame as per Kurt-Dekker's suggestions)... My issue was using 'realtimeSinceStartup' in my Singleton and comparing to a timer that used "Time.time" in the other Update() function.
     
    Last edited: Nov 9, 2022
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    If you set isloading = true and then go DO the heavy computations, your ticker won't update until AFTER you are done

    Steps to success: set loading true, yield a frame, THEN do your heavy comps.

    Generally:

    Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

    Nothing will render, no input will be processed, no Debug.Log() will come out, no GameObjects or transforms will appear to update.

    Absolutely NOTHING will happen... until your code either:

    - returns from whatever function it is running

    - yields from whatever coroutine it is running

    As long as your code is looping, Unity isn't going to do even a single frame of change. Nothing.

    No exceptions.

    "Yield early, yield often, yield like your game depends on it... it does!" - Kurt Dekker
     
  3. justin_kasowski

    justin_kasowski

    Joined:
    Jan 14, 2020
    Posts:
    45
    I should have mentioned, I also set the loading screen to be on in the singleton before running the computations. So in theory, it should flip the loading screen on (which it does) and it should be staying on until after the computations finish (which doesn't seem to happen). I'll try to yield a frame and see if it changes anything though :)
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    You're absolutely welcome to do ANYTHING you want in code before running the computations.

    Until you yield, your code and your 12 best friends will be the ONLY thing that sees what you have done.

    I'll say it again:

    Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

    Nothing will render, no input will be processed, no Debug.Log() will come out, no GameObjects or transforms will appear to update.

    Absolutely NOTHING will happen... until your code either:

    - returns from whatever function it is running

    - yields from whatever coroutine it is running

    As long as your code is looping, Unity isn't going to do even a single frame of change. Nothing.

    No exceptions.

    "Yield early, yield often, yield like your game depends on it... it does!" - Kurt Dekker
     
  5. justin_kasowski

    justin_kasowski

    Joined:
    Jan 14, 2020
    Posts:
    45
    Looking back at my code, I'm realizing I already implemented waiting a couple frames before starting the calculations:


    Code (CSharp):
    1. /// <summary>
    2.     /// Calls UpdateConfiguration every [frameDelay] frames
    3.     /// </summary>
    4.     public void UpdateAfterFrames()
    5.     {
    6.         isLoading = true;
    7.         framesToWait--;
    8.       UI_Handler.Instance.pleaseWait.enabled = true;
    9.  
    10.       vm.UpdateConfig();
    11.  
    12.       if (framesToWait <= 0 || axonMap.axonIdxStart == null)
    13.       {
    14.          
    15.           framesToWait = frameDelay;
    16.           Debug.Log("UPDATE CALLED: " +
    17.                     (vm.usePreDefinedBlock ? vm.predefinedSettings.ToString() : vm.configurationName));
    18.           UpdateConfiguration();
    19.       } }
    20.  
    21.     /// <summary>
    22.       /// Updates configuration of VariableManagerScript and electrodes
    23.       /// </summary>
    24.       private void UpdateConfiguration ()
    25.       {
    26.           isLoading = true;
    27.           vm.UpdateConfig();
    28.           electrodesHandler.SetRectangularGrid();
    29.          
    30.           if (!vm.loadFromBinaries || !File.Exists(vm.configurationPath + "_axonElectrodeGauss")){
    31.               if (vm.useAxonMap)
    32.                   axonMapHandler.SetAxonsAndElectrodesGauss();
    33.           } else
    34.               LoadBinaryData();
    35.          
    36.           allMaxElectrodes = electrodes;
    37.                     for (int i = 0; i < allMaxElectrodes.Length; i++)
    38.                       allMaxElectrodes[i].current = 1;
    39.                    
    40.           electrodesHandler.ElectrodeGridToScreenPosCoords();
    41.           InitializeBuffers();
    42.  
    43.           resetTemporalValues = true;
    44.        
    45.          
    46.           SetRandomizerArray();
    47.           TaskHandler.Instance.trialTimer = Time.realtimeSinceStartup;
    48.           isLoading = false;
    49.       }
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    Look, just put Debug.Log() statements in, THREE of them:

    1. where you turn the loading screen on

    2. where the loading screen executes a frame and shows its prefab

    3. where you start the computation

    You expect to see 1,2,3 in the logs.

    My money is you will see 1, 3, 2 unless you are yielding or returning somewhere between 1 and 2.
     
  7. justin_kasowski

    justin_kasowski

    Joined:
    Jan 14, 2020
    Posts:
    45
    I figured out the issue, it's because I used "realtimeSinceStartup" in my singleton but was using "Time.time" when checking for time between steps that progressed by trigger press. Essentially, the "UpdateConfiguration()" function was adding whatever the calculation time was into the wait time.

    I appreciate your input, I was under the impression (from reading other posts) that Unity would automatically load the next frame if the current frame was taking too long... From what you're saying, that only happens if you manually yield the frame (which is good to know).
     
    Kurt-Dekker likes this.
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    Nope, the whole rendering->scripting loop is single-threaded. Networking and other background stuff still runs of course but nothing in the Unity window would visibly change until end of frame.

    You might also enjoy this flowchart:

    Here is some timing diagram help:

    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
    justin_kasowski likes this.
  9. justin_kasowski

    justin_kasowski

    Joined:
    Jan 14, 2020
    Posts:
    45
    Bookmarked! Wish I would've come across this flowchart a long time ago.
     
    Kurt-Dekker likes this.