Search Unity

Question How to implement function/callback which is called independent of Update/Fixed Update?

Discussion in 'Scripting' started by cb0d, Jul 2, 2022.

  1. cb0d

    cb0d

    Joined:
    Mar 18, 2022
    Posts:
    20
    I'm trying to create a function which can be called at a fixed interval, independent of the Update/Fixed Update timings. It needs be called every 5ms.

    Do I need to use a System.Threading.Timer or similar to achieve this?
     
  2. Kreshi

    Kreshi

    Joined:
    Jan 12, 2015
    Posts:
    446
    While the following code is the easiest solution:

    Code (CSharp):
    1.         // Start is called before the first frame update
    2.         void Start()
    3.         {
    4.             StartCoroutine(customLoopCoroutine());
    5.         }
    6.  
    7.         IEnumerator customLoopCoroutine()
    8.         {
    9.             while(true)
    10.             {
    11.                 customLoop();
    12.                 yield return new WaitForSeconds(0.005f);
    13.             }
    14.         }
    15.  
    16.         void customLoop()
    17.         {
    18.             // your code here
    19.         }
    You have to take into consideration, that 5ms is a very short period to run for coroutines because coroutines run on the main thread so your main thread would need to run faster than 5ms for this to work properly. Therefore using the jobs system / dedicated thread would be a better option. Also waiting 5ms like in the above example is additive waiting. Using Time.time with some custom logic would be a better option than that as well. So the solution I posted is the worst possible solution, but it's the easiest and you don't have to worry about thread safety :D (+ I am lazy af today :D).
     
    cb0d likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    You probably want to rethink any game design that relies on a timing window like this.
     
  4. cb0d

    cb0d

    Joined:
    Mar 18, 2022
    Posts:
    20
    Thank you for the response. I agree that using a coroutine wouldn't work well because it relies on the main loop which will likely be slower than 5ms. I didn't realize the job system could be utilized for something like this, I'll look into how that would work.
     
  5. cb0d

    cb0d

    Joined:
    Mar 18, 2022
    Posts:
    20
    Interesting, could you explain more as to why this should be avoided? Is it because 5ms is too frequent, and if so what would be an "appropriate" interval?
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    First, even getting it on consumer hardware is iffy, so right away your design MUST accommodate failures and unpredictable failures at that.

    Second, even if you get it 100% of the time in 5ms, 100% of what you contemplate doing in that interval has to be done within 5ms, so we're talking setting a few variables, clearing a few variables, etc., nothing at all "heavy."

    Also, in another thread, NOTHING in Unity can be manipulated. 100% of Unity has to happen on the main thread.

    Finally who is ultimately going to care about what data processing gets done in this timing interval? Whoever cares about it also has access to things like Time.deltaTime and Time.time and they can say "Oh looks like 17 of the 5ms windows has gone by, I'll do 17 steps now."

    Short of servicing some kind of hardware timing interrupt, there's almost no game problem that could be solved by the above approach.
     
    Ryiah likes this.
  7. cb0d

    cb0d

    Joined:
    Mar 18, 2022
    Posts:
    20
    That's helpful, I didn't know that Unity object couldn't be manipulated in another thread. How does this work with the job system? Is that not a way to access Unity objects outside the main thread?

    In any case, it sounds like I need to reconsider using Update/FixedUpdate for this particular system. Currently I'm using FixedUpdate and I've set the fixed time interval to 5ms, and it works great, but my fear is that this will have a negative impact on performance later down the line. Currently the performance is not impacted (600+ fps).
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,935
    This is really not the point of fixed update. It's purpose is to step in time with the physics system, and it's interval can in fact be faster or slower than the desired value depending on what else is happening within Unity.
     
  9. cb0d

    cb0d

    Joined:
    Mar 18, 2022
    Posts:
    20
    Right, I agree. This is why I originally posted to see if there is another way to get an interval faster and more consistent than the frame rate of the game.

    But do you think that running the fixed update interval at 5ms (200Hz) would cause performance issues later on?
     
  10. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,935
    It's kinda not the point. Fixed update is still frame dependant and still happens on the main thread, same as everything. Just it's only meant to be used in tune with the physics system.

    You'd get as much accuracy out of it as opposed to just having an update manager with a timer that ticks up in a Monobehaviour's Update() callback.

    If you want to get fancy you can hook into the actual PlayerLoop system, but, again, still happening on a per-frame basis.