Search Unity

Question WaitForSeconds depends on fps? Whats the best alternative?

Discussion in 'Scripting' started by foxyyhappyw, Mar 17, 2023.

  1. foxyyhappyw

    foxyyhappyw

    Joined:
    Aug 8, 2022
    Posts:
    61
    Hey,
    I need to make a mechanism that does something after exactly 5 seconds.
    Whats the best way to make it?

    as far as I know WaitForSeconds in IEnumerator is depends on fps, so it's not the best option for me.

    But what about WaitForSecondsRealtime? Or is there any other better option?
     
  2. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Wait time only depends on FPS the way everything in Unity does. WaitForSeconds(5) will wait for the next frame after 5 seconds have passed, which will be pretty close to 5 seconds. If you do it a lot and don't want those little extra times to add up, keep track of when you started and compute from there.

    Unity waiting is only based on FPS when you do very short waits. A tiny WaitForSeconds might take 2 frames at 30FPS but only 3 at 60FPS (instead of 4, which would be the same time). Then it's easier to count frames or use FixedUpdate (which is preset at around 50).
     
    Kurt-Dekker likes this.
  3. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    721
    The overarching problem here is that Unity only updates once per frame. If you want something to happen in-between two frames, then you're out of luck.

    What is the use-case here? We might be able to suggest something.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    The above two statements are unrelated.

    Did you intend to write for the first one,

    "WaitForSeconds() depends on Time.timeScale"

    ...?

    If so that is correct, so your choice then would be the realtime wait.

    Either way, 100% of Unity scripting depends, relies, and is intimately tied to the main game loop.

    Think of it as a busy train station with a published schedule.

    If you take the time to understand the schedule, you can engineer your game accordingly.

    Here is some timing diagram help, aka "The Master Train Schedule."

    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
  5. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    These words are very important. What is it doing, exactly? And what necessitates being more exact than a frame? This is very important information.

    If "something" is communicating with hardware or a network and that's why you can't be restrained by the frame time, then you're correct that you do need to be more precise than frame. For that, you have to go outside of Unity's methods, and outside of the main thread. Look for a tutorial on threaded programming and use the standard C# timing control methods, like perhaps Thread.Sleep.

    In almost any other situation, however, you do not in fact need to have it happen at precisely 5 seconds. But you might need to do a little bit of math to simulate happening at precisely 5 seconds. This is pretty much what the physics/FixedUpdate system does, and depending on what your "something" is, then running that bit of logic in FixedUpdate may do the trick.

    A common example is rhythm games. Let's say you have a song at 120 BPM, so a beat happens every 0.5 seconds. If you use WaitForSeconds(0.5f) over and over, your code will drift a little bit every beat, because WaitForSeconds starts at the *end* of the frame time, and 0.5 seconds will finish sometime in the middle of another frame, but the resulting code won't execute until the beginning of the *next* frame after that. That little fraction of a frame interval is the drift that accumulates. But, if you've kept track of the time that you started the wait, and check the time now, it's not actually that difficult to just subtract that fraction of a frame and keep the overall timing precise.

    Another example: I once wrote a tech demo of a bullet hell shooter, but I found that the bullets firing on the frame would result in unpleasant staggering of what should be beautifully evenly spaced bullets. I did the same thing as on the rhythm game example, but in the extreme. Each bullet was fired at a "virtual" time (which was calculated by just adding the interval from the previous bullet) which did not need to be a time when an actual frame happened. Upon start, that bullet would nudge its starting position based on that virtual time minus the real game time. The result was perfectly spaced bullets regardless of framerate.

    For stuff that happens purely ingame (like the above examples), the reason you shouldn't generally go into a separate thread is because you'll have to drop back into the main thread anyway in order to actually affect anything in the game.
     
    chemicalcrux likes this.