Search Unity

Version of deltaTime not affected by Time.timeScale?

Discussion in 'Scripting' started by Tuhljin, Nov 17, 2013.

  1. Tuhljin

    Tuhljin

    Joined:
    Jun 23, 2012
    Posts:
    12
    I'd like to use Time.timeScale to speed up, slow down, and pause my game, but the problem is that this makes certain scripts behave in unintended ways. For instance, my camera control script uses Time.deltaTime in order to rotate and move it around smoothly, and I don't want the current timeScale to change its speed or pause it. Is there a simple way to get a value that'd be the equivalent of Time.deltaTime if Time.timeScale were 1?

    I've searched for quite a while for an answer but it seems like the solution seems to be creating my own timeScale, plugging it in everywhere I need it, and ignoring Unity's Time.timeScale entirely, which is pretty annoying. People have suggested replacing instances of "* Time.deltaTime" with "* (Time.deltaTime / Time.timeScale)", but that's just a division by zero error waiting to happen.
     
  2. Gaski

    Gaski

    Joined:
    Jul 25, 2011
    Posts:
    84
  3. Tuhljin

    Tuhljin

    Joined:
    Jun 23, 2012
    Posts:
    12
    So does every script that needs to be independent of timeScale needs to individually track previous realTimeSinceStartup (since it will vary slightly for each)? And I suppose they'll need special logic in there if the script's Update isn't always going to be called every frame since "realTimeSinceStartup - previousRealTimeSinceStartup" is not guaranteed to be the same as deltaTime's "time in seconds it took to complete the last frame".

    It'd just be so much cleaner if Unity provided a way to get the REAL deltaTime instead of forcing timeScale on everything related to the delta. But I suppose that's the best we can do?
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Just make a function that takes timeScale into account (use Time.deltaTime / Time.timeScale but check for 0 first), and use that instead of Time.deltaTime.

    --Eric
     
    whileBreak likes this.
  5. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Make your own Time class that you can call MyTime.deltaTime, which calcs from TimeSinceStartup
     
  6. Tuhljin

    Tuhljin

    Joined:
    Jun 23, 2012
    Posts:
    12
    Checking for zero first is easy. The harder part is deciding what we'll pretend deltaTime was in the case that it was zero. It seems like I'm going to have to check against realTimeSinceStartup in that case, which brings on the issues I mentioned about that before. I guess I'll end up having a special timekeeper GameObject whose Update is always called (no disabling that component script). I'm still seeing a potential problem with that, though: There's no guarantee that the timekeeper's Update will be called before the other objects' (and I really don't want to make all of the others use LateUpdate if possible since I want to be able to guarantee those objects' Update calls run before the updates certain other scripts use). Perhaps it's the best we can do and I'll just have to deal with the delta possibly being a bit off once in a while; it might not even be noticeable on the users' end.

    All that said, what do you think of this solution?

    Code (csharp):
    1. public class Timekeeper : MonoBehaviour {
    2.     private float prevRealTime;
    3.     private float thisRealTime;
    4.  
    5.     void Update () {
    6.         prevRealTime = thisRealTime;
    7.         thisRealTime = Time.realtimeSinceStartup;
    8.     }
    9.    
    10.     public float deltaTime {
    11.         get {
    12.             if (Time.timeScale > 0f)  return  Time.deltaTime / Time.timeScale;
    13.             return Time.realtimeSinceStartup - prevRealTime; // Checks realtimeSinceStartup again because it may have changed since Update was called
    14.         }
    15.     }
    16. }
     
  7. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
  8. Tuhljin

    Tuhljin

    Joined:
    Jun 23, 2012
    Posts:
    12
    Ah, beautiful! Why didn't I know about this before? Thanks.
     
  9. Astiolo

    Astiolo

    Joined:
    Dec 18, 2014
    Posts:
    27
  10. Xonatron

    Xonatron

    Joined:
    Jan 14, 2013
    Posts:
    31
    EDIT: This post is wrong. There was a bug in my code. Keep reading the thread past this.

    Time.unscaledDeltaTime actually is still affected and changed by Time.timeScale. I just tried it out. It appears that Time.realtimeSinceStartup is the only solution.
     
    Last edited: Jan 18, 2018
  11. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    unscaledDeltaTime isn't affected by timeScale. Even if it was, realtimeSinceStartup isn't a real solution since the precision degrades too much after a few days of runtime. See my post above for a better solution, or just use unscaledDeltaTime since it does work.

    --Eric
     
    DonLoquacious likes this.
  12. Xonatron

    Xonatron

    Joined:
    Jan 14, 2013
    Posts:
    31
    You are right. I was wrong. I just did another test and verified so. My previous test had a bug in it's code. Thanks so much! I will edit my previous reply to not mislead anyone.
     
  13. mehdi-IG

    mehdi-IG

    Joined:
    Jan 26, 2018
    Posts:
    1
    hey man! you can use Time.unscaledDeltaTime insted, it s indepandant from TimeScale
     
  14. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, that was already discussed.

    --Eric
     
  15. sjakur

    sjakur

    Joined:
    Apr 24, 2016
    Posts:
    4