Search Unity

Time.timeScale doesn't affect Time.deltaTime?

Discussion in 'Scripting' started by ArenMook, Jun 3, 2012.

  1. ArenMook

    ArenMook

    Joined:
    Oct 20, 2010
    Posts:
    1,902
    So... here's a script:

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class Test : MonoBehaviour
    4. {
    5.     void Start ()
    6.     {
    7.         Time.timeScale = 0f;
    8.     }
    9.  
    10.     void Update ()
    11.     {
    12.         Debug.Log(Time.deltaTime);
    13.     }
    14. }
    Debug log keeps outputting 0.02 when I attach it and run the scene.

    If I open up the Time Manager while the application is running, I can see that the Time Scale is at 0. Peachy. But here's a kicker: if I now modify this value, say set it to 1 then back to 0, guess what happens? Debug.Log is now outputting zeroes.

    Wtf? Bug?

    P.S. "Except for realtimeSinceStartup, timeScale affects all the time and delta time measuring variables of the Time class." -- quote from http://unity3d.com/support/documentation/ScriptReference/Time-timeScale.html
     
  2. ArenMook

    ArenMook

    Joined:
    Oct 20, 2010
    Posts:
    1,902
  3. kingcharizard

    kingcharizard

    Joined:
    Jun 30, 2011
    Posts:
    1,137
    The way I have understood Time.timeScale was that it doesn't actually stop the game completely it just slows it down. So setting Time.timeScale slows the game to about 0.00000001, which is why you could be seeing the 0.02 in the debug check. Update is still called. Fixed update however wouldn't be, perhaps this would help

    API Docs
     
  4. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    5,618
    Time.deltaTime is the time that has passed since the last frame was rendered, why would it be affected by the timeScale?
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,089
    Because otherwise it would be useless. If deltaTime wasn't affected by timeScale, then code like "transform.Translate(Vector3.right * Time.deltaTime);" wouldn't behave as expected.

    That depends on the value of timeScale. If you set it to 0, then everything is stopped.

    If you're talking about setting timeScale to 0, then no, that's not what happens.

    No, the value should be 0, but I guess that might cause division by zero problems somewhere. Not that arbitrarily using .02 instead is much better....

    --Eric
     
  6. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    5,618
    Hmm good point.
     
  7. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    11,788
    That's a reasonable enough concern, but I use timeScale = 0 a fair bit and it's never caused problems.
     
  8. superpig

    superpig

    Quis aedificabit ipsos aedificatores? Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,154
    Yeah I use Time.timeScale = 0 for pausing the game too and it works fine.

    Have you tried yielding a couple of frames in your Start() method before setting the timescale to zero? From reading the link you gave it sounds like the problem only arises if you're altering the timescale in the first couple of frames of playmode.
     
    Kiwasi likes this.
  9. ArenMook

    ArenMook

    Joined:
    Oct 20, 2010
    Posts:
    1,902
    Yeah, waiting until the next frame works, but it's a hack around a problem.

    I ended up just adding if (Time.timeScale == 0f) return; everywhere. It's a bit less of a hack.
     
  10. kenlane22

    kenlane22

    Joined:
    Sep 12, 2012
    Posts:
    5
    Found this discussion in my hour of need and thought I'd share my solution to a need to speed things up or slow things down.
    I ended up replacing in all files (Ctrl-Shift-H) all references of "Time.deltaTime" with
    "(Time.deltaTime * Time.timeScale)" to get things working the way I had imagined they would.
    Paired with the if (Time.timeScale == 0f) return; pattern, I feel like I have an ok way to manage using Time.timeScale more effectively.
    -Ken =]
     
    DigitalGamez likes this.
  11. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    11,788
    What's your use case? Note that Aren's bug seems isolated to setting time scale in Start on the first frame.

    Your solution there would actually cause a lot of problems. For instance, a time scale of 0.1 would result in an applied scale of (0.1 * 0.1 = 0.01). Or, as another example, setting time scale to 0.5 would end up applying 0.25.

    If you need to apply that to all of your code, I suspect that something is wrong at a pretty fundamental level somewhere. Either the time system is doing something super wrong for you, or you're using the time values in an, ah, rather unusual way...

    I mess with time scale a fair bit while debugging. For instance, if I want to get something subtle right I'll often whack a script in my scene that drops the time scale to a small value when a button is held. Or I'll have a few buttons to dynamically speed up and slow time down. Whenever I do any of the above I can mash those keys like crazy and nothing goes wrong...
     
    Last edited: Feb 19, 2014
  12. kenlane22

    kenlane22

    Joined:
    Sep 12, 2012
    Posts:
    5
    AngryPenguin,
    You are right. I was wrong.
    My trouble was elsewhere.
    Thanks for the thoughtful reply.
    -Ken =]
     
    chelnok likes this.
  13. Stepepper

    Stepepper

    Joined:
    Aug 1, 2013
    Posts:
    14
    Excuse me for reviving an almost year old thread, but it seems like it was revived quite some times anyway.
    I just stumbled on this thread while researching the difference between Time.deltaTime and Time.fixedDeltaTime.
    But couldn't you just use Time.fixedDeltaTime instead because that's the one that's tied to Time.timeScale while Time.deltaTime is not?

    Damn this thread is almost 3 years old, triple my excuse then.
     
  14. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,089
    Time.deltaTime is the time between frames (Update), Time.fixedDeltaTime is the time between physics frames (FixedUpdate). You can't use Time.fixedDeltaTime to replace Time.deltaTime.

    --Eric
     
  15. Ludiq

    Ludiq

    Joined:
    Mar 6, 2015
    Posts:
    551
    Bumping this as I've found some weeeeeird undocumented behaviour while trying to fix a bug for Chronos.

    Time.unscaledDeltaTime is consistent and understandable: it always returns the time elapsed since the last frame.

    Time.deltaTime is... very odd. Buglike-odd.

    1. For the first 2 frames (Time.frameCount <= 2), it will return 0.02. No matter what. That's been somewhat noticed here, but nowhere else as far as I know. That 0.02 seems arbitrary -- it's not the fixed timestep assigned in the Project Settings > Time window (even though, by default, it has the same value). Why arbitrarily 0.02? Why arbitrarily 2 frames? Is this something we can rely on?

    2. Afterwards, it will take in consideration Time.maximumDeltaTime, unlike unscaledDeltaTime (which is perfectly fine and not buggy per se, but it's not correctly documented).

    3. Most importantly and most unpredictably, it takes some weird values after pausing and playing in the editor. Somehow, I guess it tries to compensate for the long time that elapsed. For instance, if you pause for 15 seconds, unscaledDeltaTime will be 15 seconds, but deltaTime will be something in the order of magnitude of 0.0002###. Why? This is undocumented and, from an observation standpoint, I can't see the logic behind.

    These are breaking bugs for me because I'd like to use unscaledDeltaTime (ignoring timeScale), but still have it behave like deltaTime in the editor. I can fix 1 and 2 with this (so-hacky-it-should-be-illegal-) code, but not 3:

    Code (CSharp):
    1. public static float adjustedUnscaledDeltaTime()
    2. {
    3.     if (Time.frameCount <= 2)
    4.     {
    5.         return 0.02f; // but whyyyyyyy?!
    6.     }
    7.     else
    8.     {
    9.         return Mathf.Min(Time.unscaledDeltaTime, Time.maximumDeltaTime);
    10.     }
    11. }
    12.  
    @Eric5h5, any idea?
     
  16. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,379
    If accurate time keeping for the first two frames is essential, simply do nothing for these two frames and start later.

    In actuate time keeping for a couple of frames in the editor can hardly be called a breaking bug. Sure it's annoying. But we don't make games designed to be run in the editor.

    To be honest I was never even aware of these two bugs, and have never had issues because of them. I would be curious to see a test case for why they actually matter.
     
  17. Ludiq

    Ludiq

    Joined:
    Mar 6, 2015
    Posts:
    551
    The simplest and most common case I can find: use Time.unscaledDeltaTime for your GUI to have animations while gameplay is paused (Time.timeScale = 0). Pause during a transition for a couple of seconds. When you unpause, the animation will play almost instantly because of the delay.

    But in my case, I can't predict the end-user scenario: I'm providing a plugin, and it has to work every time for my users. Most importantly, bugs and undocumented behaviour shouldn't be dismissed simply because they're not "annoying" enough.
     
    TooManySugar, mcmorry and Kiwasi like this.
  18. TooManySugar

    TooManySugar

    Joined:
    Aug 2, 2015
    Posts:
    864
    ludic's answers is the correct one.

    I was getting mad. I had this timer script, instead of unscaleddeltatime I had time.deltatime. My time scale was 1.4, definetly the timer was affected by timescale. Now is not.

    Code (CSharp):
    1. public class Timer : MonoBehaviour {
    2.  
    3.     private Game_Controller_CS _GC;
    4.  
    5.     public bool minsec;
    6.     public bool milisec;
    7.  
    8.     private Text time_Txt;
    9.     private string niceTime;
    10.  
    11.  
    12.     void Start () {
    13.         _GC =Game_Controller_CS.Game_Controller;
    14.  
    15.         time_Txt = transform.GetComponent<Text>();
    16.         timer=0f;
    17.     }
    18.  
    19.     private float timer;
    20.    
    21.     void Update () {
    22.  
    23.         if (_GC.playerSpawned) timer += Time.unscaledDeltaTime;
    24.  
    25.         if(minsec){
    26.         int minutes = Mathf.FloorToInt(timer / 60F);
    27.         int seconds = Mathf.FloorToInt(timer - minutes * 60);
    28.    
    29.         niceTime = string.Format("{0:00}:{1:00}", minutes, seconds);
    30.         }
    31.  
    32.         if(milisec){
    33.             int milisecs = Mathf.FloorToInt((timer*10) % 10);//miliseconds
    34.             niceTime = string.Format("{0:0}",  milisecs);
    35.         }
    36.  
    37.         time_Txt.text = niceTime;
    38.     }
    39. }