Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Potential issue with Time.unscaledDeltaTime on 2018.2.20f1

Discussion in 'Android' started by claytoncurmi, Apr 24, 2019.

  1. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    Hi all,

    I am encountering an issue with the Time.unscaledDeltaTime not being properly set when the application is paused or out of focus. I am running the following script on Android device using builds from 2017.2.0f3 and 2018.2.20f1. This is the scenario I am trying;
    • Launch application
    • Once loaded, I lock the device
      • I start a timer (on another device) to keep track of how long the game has been actually suspended
    • I press the lock button on the device again and the application is resumed
      • Simultaneously I stop the timer
    • The first Update call that gets executed should report that the Time.unscaledDeltaTime since last frame
      • The expected result is that the Time.unscaledDeltaTime is equal to the time that the application has been paused (roughly the same to that reported by the timer)
      • What I actually get is a value less than expected, say if the game has been suspended for 40s the Time.unscaledDeltaTime is set to 16s.
    • This behaviour was noticed in 2018.2.20f1 but not reproducible on 2017.2.0f3 (works correctly here)
    Can someone verify or explain why this is happening?

    Code (CSharp):
    1. using System;
    2. using System.Text;
    3. using UnityEngine;
    4.  
    5. public class TimeDemo : MonoBehaviour
    6. {
    7.     private bool logNextDeltaTime;
    8.     private float lastUnscaledTime;
    9.     private StringBuilder logBuilder;
    10.  
    11.     private void Awake()
    12.     {
    13.         logBuilder = new StringBuilder();
    14.     }
    15.  
    16.     private void Update()
    17.     {
    18.         if (logNextDeltaTime)
    19.         {
    20.             var diff = Time.unscaledTime - lastUnscaledTime;
    21.             logBuilder.AppendLine(string.Format("Application is updating frame {0} with time {1} (+{2}s). Time difference should be +{3}s", Time.frameCount, Time.unscaledTime, Time.unscaledDeltaTime, diff));
    22.             logNextDeltaTime = false;
    23.         }
    24.     }
    25.  
    26.     private void OnApplicationFocus(bool focus)
    27.     {
    28.         logBuilder.AppendLine(string.Format("Application is focused - {0} in frame {1} with time {2}", focus, Time.frameCount, Time.unscaledTime));
    29.         if (!focus)
    30.         {
    31.             logBuilder.AppendLine(string.Format("Last unscaled time {0}", Time.unscaledTime));
    32.             lastUnscaledTime = Time.unscaledTime;
    33.             logNextDeltaTime = true;
    34.         }
    35.     }
    36.  
    37.     private void OnApplicationPause(bool pause)
    38.     {
    39.         logBuilder.AppendLine(string.Format("Application is paused - {0} in frame {1} with time {2}", pause, Time.frameCount, Time.unscaledTime));
    40.         if (pause)
    41.         {
    42.             logBuilder.AppendLine(string.Format("Last unscaled time {0}", Time.unscaledTime));
    43.             lastUnscaledTime = Time.unscaledTime;
    44.             logNextDeltaTime = true;
    45.         }
    46.     }
    47.  
    48.     private void OnGUI()
    49.     {
    50.         GUI.skin.GetStyle("label").fontSize = 35;
    51.         GUI.skin.GetStyle("button").fontSize = 35;
    52.  
    53.         if(GUILayout.Button("Clear Log", GUILayout.Width(300), GUILayout.Height(100)))
    54.         {
    55.             logBuilder = new StringBuilder();
    56.         }
    57.  
    58.         GUILayout.Label(logBuilder.ToString());
    59.     }
    60. }
     
  2. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    A weird fact that I noticed is that when the Android device is connected via USB with the machine, the unscaledDeltaTime values are correct. When it is disconnected, it doesn't work as expected. I updated the code to use the Android elapsedTime from its local clock and the values received are correct as seen in Unity 2017.2.0f3.

    Can someone confirm this issue?

    Code (CSharp):
    1. using System;
    2. using System.Text;
    3. using UnityEngine;
    4.  
    5. public class TimeDemo : MonoBehaviour
    6. {
    7.     private bool logNextDeltaTime;
    8.     private float prevTimestamp;
    9.     private StringBuilder logBuilder;
    10.  
    11.     private void Awake()
    12.     {
    13.         logBuilder = new StringBuilder();
    14.     }
    15.  
    16.     private void Update()
    17.     {
    18.         if (logNextDeltaTime)
    19.         {
    20.             #if UNITY_ANDROID && !UNITY_EDITOR
    21.             var currTimestamp = UnscaledTime();
    22.             #else
    23.             var currTimestamp = Time.unscaledTime;
    24.             #endif
    25.  
    26.             var diff = currTimestamp - prevTimestamp;
    27.             logBuilder.AppendLine(string.Format("Application is updating frame {0} with time {1} (+{2}s). Time difference should be +{3}s", Time.frameCount, Time.unscaledTime, Time.unscaledDeltaTime, diff));
    28.             logNextDeltaTime = false;
    29.         }
    30.     }
    31.  
    32.     private void OnApplicationFocus(bool focus)
    33.     {
    34.         logBuilder.AppendLine(string.Format("Application is focused - {0} in frame {1} with time {2}", focus, Time.frameCount, Time.unscaledTime));
    35.         if (!focus)
    36.         {
    37.             OnSuspended();
    38.         }
    39.     }
    40.  
    41.     private void OnApplicationPause(bool pause)
    42.     {
    43.         logBuilder.AppendLine(string.Format("Application is paused - {0} in frame {1} with time {2}", pause, Time.frameCount, Time.unscaledTime));
    44.         if (pause)
    45.         {
    46.             OnSuspended();
    47.         }
    48.     }
    49.  
    50.     private void OnGUI()
    51.     {
    52.         GUI.skin.GetStyle("label").fontSize = 35;
    53.         GUI.skin.GetStyle("button").fontSize = 35;
    54.  
    55.         if(GUILayout.Button("Clear Log", GUILayout.Width(300), GUILayout.Height(100)))
    56.         {
    57.             logBuilder = new StringBuilder();
    58.         }
    59.  
    60.         GUILayout.Label(logBuilder.ToString());
    61.     }
    62.  
    63.     private void OnSuspended()
    64.     {
    65.         #if UNITY_ANDROID && !UNITY_EDITOR
    66.         prevTimestamp = UnscaledTime();
    67.         #else
    68.         prevTimestamp = Time.unscaledTime;
    69.         #endif
    70.  
    71.         logNextDeltaTime = true;
    72.         logBuilder.AppendLine(string.Format("Last unscaled time {0}", prevTimestamp));
    73.     }
    74.  
    75.     private float UnscaledTime()
    76.     {
    77.         var systemClock = new AndroidJavaClass("android.os.SystemClock");
    78.         return systemClock.CallStatic<long>("elapsedRealtime") / 1000f;
    79.     }
    80. }
     
  3. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,873
    Can you try with 2018.3 ?

    Long story short, android system timer sometimes jumps back... don't remember the details, but there is faulty implementation in Android OS itself.

    There were numerous attempts to workaround that, I think one workaround was applied in 2017, but then reverted back, because it created a new issue. (This might be what you're seeing)

    But then there was a more stable workaround done in 2018.3.
     
  4. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    Thanks for your reply and explanation. Unfortunately, we cannot update to 2018.3 for the time being. Found a different approach by using android.os.SystemClock as shown in the previous code sample.

    Thanks
     
    Tomas1856 likes this.