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

Is it possible to schedule a coroutine to run at the time of LateUpdate?

Discussion in 'Scripting' started by PhoenixRising1, Oct 6, 2015.

  1. PhoenixRising1

    PhoenixRising1

    Joined:
    Sep 12, 2015
    Posts:
    488
    I have some graphical indicators that I need to run at a lateupdate, they simply need to get calculated after everything else, but I also don't want the LateUpdate to run every frame to check if there is anything to update.

    WaitForEndOfFrame doesn't work since it will run after the GUI is updated.

    Didn't find any documentation on it being possible to enable and disable the LateUpdate function, so if anyone has any idea how to solve this please let me know :).
     
  2. goonter

    goonter

    Joined:
    Aug 31, 2015
    Posts:
    89
    I'd do something like this:

    Code (CSharp):
    1. float lastUpdate;
    2. float updateInterval = 1.0f;
    3.  
    4. void LateUpdate()
    5. {
    6.    if (Time.time > lastUpdate + updateInterval)
    7.    {
    8.       RefreshIndicators();
    9.       lastUpdate = Time.time;
    10.    }
    11. }
     
  3. PhoenixRising1

    PhoenixRising1

    Joined:
    Sep 12, 2015
    Posts:
    488
    I'm already doing a check in my current LateUpdate() to see if anything needs updating - which only checks if a boolean is true - but thanks anyway :).
     
  4. goonter

    goonter

    Joined:
    Aug 31, 2015
    Posts:
    89
    Well the cost of checking a boolean every frame is small, as long as it isn't a property using a complex Get implementation, I'd just stick with that.
     
  5. PhoenixRising1

    PhoenixRising1

    Joined:
    Sep 12, 2015
    Posts:
    488
    That's true but I want to try to optimize my code as much as I can. However if it's not possible I'll just stick with the boolean, but we'll see if anyone has a solution :).
     
  6. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    The way you are doing it is already the fastest.

    A solution involving a coroutine would be way less optimal.

    No matter how you slice it, weather its in your code or somewhere else, something needs to be checked every frame.
     
    shaderop and PhoenixRising1 like this.
  7. PhoenixRising1

    PhoenixRising1

    Joined:
    Sep 12, 2015
    Posts:
    488
    Ok, thanks for the input.
     
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Check out @lordofduct's frame work. He has hooks all over the place for various events. If you are interested in doing this a lot, its worth writing some of your own frame work.
     
    PhoenixRising1 likes this.
  9. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,514
    So, I'm not sure what your design is. But I'm going to guess that the operation that occurs in 'LateUpdate' only occurs on some other event.

    Like:

    Code (csharp):
    1.  
    2. private bool _needsUpdate = false;
    3.      
    4. void SignalChange()
    5. {
    6.     _needsUpdate = true;
    7. }
    8.  
    9. void LateUpdate()
    10. {
    11.     if (_needsUpdate)
    12.     {
    13.         //perform some task
    14.         _lateUpdate = false;
    15.     }
    16. }
    17.  
    18.  
    This method might be called very infrequently, so you don't want to waste checking if 'needsUpdate' every frame if it happens once a minute or something?

    Am I correct in assuming this?


    If this is so, it is true, BenZed is correct in that something has to poll the LateUpdate event, because it's the only hook into that event that exists.

    Personally I have a global Singleton that I use to hook into the events. This way each is only polled as few times as I need... instead of EVERY script polling it every frame.

    This is it:
    https://github.com/lordofduct/spacepuppy-unity-framework/blob/master/SpacepuppyBase/GameLoopEntry.cs

    I actually poll 3 times per update type. An early one (script flagged to operate at order -32000), a normal (script not given an execution order), and a script that is flagged to operate last (32000 execution order). This way I can hook in at any point.

    I always did it with .net events (as you can see the static 'event' members of GameLoopEntry).

    But I recently added a way to call a single function one time, and wanted it to have multithreading support. So that way from a separate thread I could just call back to the main thread and do something.

    That's what I wrote the 'InvokePump' for:
    https://github.com/lordofduct/space...lob/master/SpacepuppyBase/Async/InvokePump.cs

    I gave GameLoopEntry 2 pumps, one for 'Update' and one for 'FixedUpdate'. I never actually added one for 'LateUpdate' though, as I never really use 'LateUpdate' for anything. But it could be easily added... just mirror the way 'Update' and 'FixedUpdate' do it:

    Code (csharp):
    1.  
    2.         //Update
    3.  
    4.         private void Update()
    5.         {
    6.             //Track entry into update loop
    7.             _currentSequence = UpdateSequence.Update;
    8.  
    9.             if (_internalEarlyUpdate != null) _internalEarlyUpdate(false);
    10.  
    11.             _invokePump.Update();
    12.  
    13.             if (EarlyUpdate != null) EarlyUpdate(this, System.EventArgs.Empty);
    14.         }
    15.  
    16.         //Fixed Update
    17.  
    18.         private void FixedUpdate()
    19.         {
    20.             //Track entry into fixedupdate loop
    21.             _currentSequence = UpdateSequence.FixedUpdate;
    22.  
    23.             if (_internalEarlyUpdate != null) _internalEarlyUpdate(true);
    24.  
    25.             _fixedInvokePump.Update();
    26.  
    27.             if (EarlyFixedUpdate != null) EarlyFixedUpdate(this, System.EventArgs.Empty);
    28.         }
    29.  
    30.         //LateUpdate
    31.  
    32.         private void LateUpdate()
    33.         {
    34.             _currentSequence = UpdateSequence.LateUpdate;
    35.            
    36.             //INSERT INVOKEPUMP UPDATE CALL HERE
    37.            
    38.             if (EarlyLateUpdate != null) EarlyLateUpdate(this, System.EventArgs.Empty);
    39.         }
    40.  
    Then the syntax would simply be:

    Code (csharp):
    1.  
    2. void SignalChange()
    3. {
    4.     GameLoopEntry.LateUpdatePump.BeginInvoke(this.PerformOnLateUpdate);
    5. }
    6.  
    7. void PerformOnLateUpdate()
    8. {
    9.     //perform some task
    10. }
    11.  
     
    Last edited: Oct 7, 2015
    kiber_, tcmeric, BenZed and 1 other person like this.
  10. PhoenixRising1

    PhoenixRising1

    Joined:
    Sep 12, 2015
    Posts:
    488
    Hi. I just noticed the post and I will have to read it tomorrow, gonna hop into bed now. Thanks for the reply.
     
  11. PhoenixRising1

    PhoenixRising1

    Joined:
    Sep 12, 2015
    Posts:
    488
    After having read your code I have decided to just disable the script when it's not needed instead, since the script will only be needed for like a minute at a time, and then rest for a few minutes. You've done a very nice job but I was hoping for some easy solution :) (I'm still very new to unity and programming). But I have bookmarked this page and will come back to it once I get more knowledge. Thank you.
     
    harold_unity365 likes this.