Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

realtimeSinceStartup is not 0 in first Awake() call?

Discussion in 'Editor & General Support' started by gtzpower, Oct 18, 2013.

  1. gtzpower

    gtzpower

    Joined:
    Jan 23, 2011
    Posts:
    318
    Does anyone know why realtimeSinceStartup would be non-zero at startup (Awake function called after scene loaded)? I am getting a random value typically between 0 and 60, and it is throwing off custom timers that are independant of timescale. So frame by frame, it returns:

    38.151 (random)
    0.0016
    0.0032
    0.0048

    Any thoughts? I am about to hack around it by checking if it is the first frame and using 0 instead, but would prefer to figure out the problem.

    Thanks!
     
  2. Graham-Dunnett

    Graham-Dunnett

    Unity Technologies

    Joined:
    Jun 2, 2009
    Posts:
    4,287
    It's just how it works. All the gameobjects awake, and then the game starts at t=0.
     
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    realtimeSinceStartup is continuous and means exactly what it says, not like Time.time or Time.deltaTime where there is a fixed value per frame. For example, t1 and t2 will have different values in the same function:

    Code (csharp):
    1. var t1 = Time.realtimeSinceStartup;
    2. Debug.Log (t1);
    3. var t2 = Time.realtimeSinceStartup;
    4. Debug.Log (t2);
    It would never be 0.0 unless that was the very first thing that Unity did immediately after startup, which wouldn't happen. However there shouldn't be any random values in the first frame either, and there used to not be in 3.x, so I'd say that's a bug that was introduced at some point in the 4.x series.

    --Eric
     
    Turbo420 likes this.
  4. gtzpower

    gtzpower

    Joined:
    Jan 23, 2011
    Posts:
    318
    Okay, thanks guys. I'll just work around the issue then.
     
  5. Luke-Kellett

    Luke-Kellett

    Joined:
    Oct 22, 2011
    Posts:
    9
    I've run into the same problem with my own custom timers for both Time.realtimeSinceStartup and Time.frameCount.

    Running my own test script in an empty scene I found the following results.

    In the editor on Awake()
    Time.realtimeSinceStartup will return the time elapsed since the last editor play mode
    Time.frameCount will not return 0 but it's not a very high number either, no idea where it gets the value from
    Time.time will return 0

    In the editor on Start()
    Time.realtimeSinceStartup will return the time elapsed since actual play mode start
    Time.frameCount will return the actual frame count being 1
    Time.time will return 0

    On an iOS device on Awake()
    Time.realtimeSinceStartup will return a non-zero value, perhaps the time it has taken to deserialize data in the first scene
    Time.frameCount will return 0
    Time.time will return 0

    In the editor on Start()
    Time.realtimeSinceStartup will return the expected value
    Time.frameCount will return the actual frame count being 1
    Time.time will return 0


    So as a work around I am using is to see if Time.time is 0, and if it is use 0... Otherwise use the value returned by Time.realtimeSinceStartup.

    That said, this feels more like a bug than something that is by design. Going by the Unity documentation that is.
     
    Last edited: Oct 20, 2013
  6. gtzpower

    gtzpower

    Joined:
    Jan 23, 2011
    Posts:
    318
    Thanks! I will verify that I get the same result on my end and if I do, this would be a much cleaner workaround than what I had planned on doing.

    Thanks again for your experience :)
     
  7. Luke-Kellett

    Luke-Kellett

    Joined:
    Oct 22, 2011
    Posts:
    9
    No worries, I'm actually using the same workaround on devices too... I should have amended my first post after I did extra testing :p
     
  8. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
  9. Graham-Dunnett

    Graham-Dunnett

    Unity Technologies

    Joined:
    Jun 2, 2009
    Posts:
    4,287
    (I think it's safe to assume that a bug reported in 3.4 isn't about to get fixed any time. Awake() should be used to get the GO up and running, and not change it's behaviour based on game state.)
     
  10. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    I see your point, but according to the documentation of Awake you can also initialize variables:
    A float is initialized with the passed time since the start, which should clearly be zero.

    The documentation for realtimeSinceStartup is pretty precise and doesn't mentions any exceptions:
    I can certainly live with the current situation as there are pretty simple workarounds. That's the way it is. But it doesn't change the fact that this is a bug. The value is set too late within Unity.
     
  11. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,148
    Another issue along the same lines (and mentioned by another user) is the behaviour of Time.frameCount.

    Take this script:

    Code (csharp):
    1. public class FrameCountTester : MonoBehaviour
    2. {
    3.     public string levelName = "Level";
    4.     public bool loadLevel = false;
    5.     int x = 0;
    6.    
    7.     void Awake()
    8.     {
    9.         Debug.Log("Awake " + levelName + ": " + Output());
    10.     }
    11.  
    12.     void OnEnable()
    13.     {
    14.         Debug.Log("OnEnable " + levelName + ": " + Output());
    15.     }
    16.  
    17.     void Start ()
    18.     {
    19.         Debug.Log("Start " + levelName + ": " + Output());
    20.     }
    21.  
    22.     void Update()
    23.     {
    24.         if (x++ == 0)
    25.         {
    26.             Debug.Log("Update " + levelName + ": " + Output());
    27.             if (loadLevel)
    28.                 Application.LoadLevel(1);
    29.         }
    30.     }
    31.  
    32.     string Output()
    33.     {
    34.         return "Frame Count = " + Time.frameCount.ToString();
    35.     }
    36. }
    In my initial scene, I have this script with levelName set to "Level 1" and loadLevel set to true. In the second scene (scene index 1), I have this script with level name set to "Level 2" and loadLevel set to false.

    Output in the Editor:
    Awake Level 1: Frame Count = 1
    OnEnable Level 1: Frame Count = 1
    Start Level 1: Frame Count = 1
    Update Level 1: Frame Count = 1
    Awake Level 2: Frame Count = 2
    OnEnable Level 2: Frame Count = 2
    Start Level 2: Frame Count = 2
    Update Level 2: Frame Count = 2

    Output in Standalone PC Build:
    Awake Level 1: Frame Count = 0
    OnEnable Level 1: Frame Count = 0
    Start Level 1: Frame Count = 1
    Update Level 1: Frame Count = 1
    Awake Level 2: Frame Count = 2
    OnEnable Level 2: Frame Count = 2
    Start Level 2: Frame Count = 2
    Update Level 2: Frame Count = 2

    Both outputs do not make sense.

    In the editor, why do Awake/OnEnable, Start, and Update have the same frame count?

    For the standalone build, the Level 1 Awake/OnEnable frame count of 0 is what I'd expect, as well as the 1 for Start. But why is Update also 1, and why are the Awake/OnEnable, Start and Update frame counts for level 2 all 2? At the very least, they should follow the same pattern as level 1.

    It's not cool that there are several different patterns Unity seems to be following. One standardized pattern would be a lot clearer and more useful.
     
  12. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,148
    Also, Time.timeSinceLevelLoad is reset just before Start when a new scene is loaded. Why? Wouldn't it make more sense to reset this variable before Awakes are called on a new scene load?

    Right now if you have Scene 1 loaded and load Scene 2 (non additively), you get this:

    Awake Time.timeSinceLevelLoad = time since Scene 1 was loaded (let's say 350.211s)
    OnEnable Time.timeSinceLevelLoad = 350.211
    Start Time.timeSinceLevelLoad = 0

    I think it would be more useful to have this:

    Awake Time.timeSinceLevelLoad = 0
    OnEnable Time.timeSinceLevelLoad = 0
    Start Time.timeSinceLevelLoad = time since timeSinceLevelLoad was reset to 0 (let's say .02s)

    With this method, the user would be able to say definitively that when Time.timeSinceLevelLoad == 0, Unity is in the initial post scene load Awake/OnEnable frame.
     
  13. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
  14. TobiasW

    TobiasW

    Joined:
    Jun 18, 2011
    Posts:
    86
    In version 4.2.2f1 (no idea if it's in the current version too), I just found an unexpected side effect of this bug:
    1. Time.frameCount starts with some seemingly random value - let's assume 260
    2. OnEnable() starts a Coroutine
    3. The Coroutine executes yield return null; (waiting till the next frame, which is 261)
    4. After the Awake/OnEnable phase, Time.frameCount is set to 1
    5. The Coroutine will now wait for 260 frames until frame 261
    I assumed that "yield return null;" does nothing but yielding until the next coroutine execution block. Apparently it saves the target frame though - which shouldn't be a problem, EXCEPT when Time.frameCount has some random value.

    I guess that explains why my Coroutines sometimes seemingly didn't work in Awake()...
     
  15. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,148
    This bug was reported in Unity 3.5, and still has not been resolved. It shouldn't be difficult to fix, one would think. They're aware of it obviously.
     
  16. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Any news about this bug? It's an oooold one :/
     
  17. capyvara

    capyvara

    Joined:
    Mar 11, 2010
    Posts:
    80
    Bump.

    Took me 2h searching for a bug caused by this.
     
  18. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,489
    Unity 4.5.5 and this silly bug still isn't fixed.

    On the first Awake call, Time.realtimeSinceStartup returns the time since the last stop of the editor play mode as it does when called from an editor script. On the next update, it's cleared to 0 and then counting begins from there.

    It seems to me it would be as simple as updating the Time state BEFORE making any MonoBehavior.Awake calls after the editor changes play modes. Obviously this isn't what's happening.
     
    Last edited: Nov 6, 2014
  19. Graham-Dunnett

    Graham-Dunnett

    Unity Technologies

    Joined:
    Jun 2, 2009
    Posts:
    4,287
    Looks like 5.0 will see this change. It's not been released previously, because it's a breaking change.
     
    guavaman likes this.
  20. Enemby

    Enemby

    Joined:
    Feb 24, 2015
    Posts:
    1
    I've just run into this too, in that an OnEnable call, for whatever reason, even well after scene load,

    Time.timesincelevelload will ALWAYS output 0. on the first loaded level

    Seems completely useless in this context..


    It's worth stating that I'm using 5.0, so it's probably fixed by now, but hey!
     
    Last edited: Dec 29, 2021