Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Ace_Oxide · Dec 27, 2016 at 07:03 AM · time.deltatime

Time.DeltaTime not correctly incrimenting timer?

So... I may just be stupid, but the simplest part of my little game here seems to be malfunctioning and I do not know why.

In short... In my GameController script (tracks everything) I have

void Start(){ float timer = 0.0f; }

void Update(){ timer += Time.deltaTime; }

Now the game displays the time it took in seconds at the end by simply setting the value of a text field to "timer.ToString();", but it's always way more than the actual time since the scene was loaded.

If my stopwatch times it at, say, 12 seconds - the timer reads over 20. I used my stopwatch to wait exactly 30 seconds, the timer read 120 seconds. I tried to find some kind of consistency to indicate the issue but there doesn't seem to be any... seems to just be fairly randomly "adding" time as it goes along. I've looked into the phenomenon of time drift but I doubt that's my problem.

EDIT: Alrighty, I'll post the full code (At least everything that contains this variable. It's gonna be long lol...

  public GameObject scrollingBackground;
 private GameObject tile1, tile2;
 private float moveSpeed, tileHeight, horizontalMoveSpeed, distanceTraveled;
 public GameObject joystick;
 public float maxShipSpeed, horizontalMovementMultiplier = 1.0f;
 public GameObject ship;
 public GameObject laserPrefab;
 public Text speedText, distanceText, scoreText;
 private float score;
 private float shipHealth, shieldHealth;
 public Image healthBar, shieldBar;
 public float asteroidDamage;
 public float shieldRechargeTimer, shieldRechargeRatePerSecond;
 private float timerForShields;
 private bool shieldIsRecharging = false;
 public GameObject shipDeathExplosion;
 private bool shipAlive = true;
 public GameObject dataTracker;
 -->    private float gameTime;
 private static DataManagerScript dataManager;

 // Use this for initialization
 void Start () {
     dataManager = DataManagerScript.dataManager;
     distanceTraveled = 0;
     tile1 = scrollingBackground.transform.GetChild(0).gameObject;
     tile2 = scrollingBackground.transform.GetChild(1).gameObject;
     tileHeight = tile1.GetComponent<Renderer>().bounds.size.y;
     moveSpeed = 0.0f;
     score = 0;
     shipHealth = 100;
     shieldHealth = 100;
     asteroidDamage = (asteroidDamage == 0) ? 10.0f : asteroidDamage;
     shieldRechargeTimer = (shieldRechargeTimer == 0) ? 5.0f : shieldRechargeTimer;
     shieldRechargeRatePerSecond = (shieldRechargeRatePerSecond == 0) ? 5.0f : shieldRechargeRatePerSecond;
     --> gameTime = 0;
 }
 
 // Update is called once per frame
 void Update () {

     //Timer
     --> gameTime += Time.deltaTime;

     //HEALTH AND SHIELDS
     //SHIELD RECHARGE
     timerForShields += Time.deltaTime;
     if (timerForShields > shieldRechargeTimer)
     {
         timerForShields = 0;
         shieldIsRecharging = true;
     }
     if (shieldHealth < 100)
     {
         shieldHealth += (shieldIsRecharging) ? shieldRechargeRatePerSecond * Time.deltaTime : 0f;
     }
     shieldHealth = (shieldHealth > 100.0f) ? 100 : shieldHealth;

     //SHIELD AND HEALTH BARS
     shieldHealth = (shieldHealth < 0) ? 0.0f : shieldHealth;
     shipHealth = (shipHealth < 0) ? 0 : shipHealth;
     if (shipAlive)
     {
         if (shipHealth <= 0)
         {
             Destroy(ship.GetComponent<MeshRenderer>());
             Instantiate(shipDeathExplosion, ship.transform.position, new Quaternion(0, 0, 0, 0));
             shipAlive = false;
             
             endGameOnDeath();
         }
     }
         shieldBar.rectTransform.localScale = new Vector3(shieldHealth / 100f, 1, 1);
         healthBar.rectTransform.localScale = new Vector3(shipHealth / 100f, 1, 1);
     

     //END HEALTH AND SHIELDS


     //If Joystick Is Down, Increase Movement Speed
     if (joystick.GetComponent<JoystickScript>().isJoystickDown())
     {
         moveSpeed += joystick.GetComponent<JoystickScript>().Vertical() * Time.deltaTime;
         
     }
     //NO GOING BACKWARDS!
     if(moveSpeed < 0)
     {
         moveSpeed = 0;
     }
     // LIMIT MAX SPEED
     moveSpeed = (moveSpeed > maxShipSpeed) ? maxShipSpeed : moveSpeed;

     // End Increase Movement Speed

     //Horizontal Movement
     if (joystick.GetComponent<JoystickScript>().isJoystickDown())
     {
         horizontalMoveSpeed = joystick.GetComponent<JoystickScript>().Horizontal();
         if (horizontalMoveSpeed > 0)
         {
             if (ship.transform.position.x < 7.5)
             {
                 ship.transform.Translate(Vector3.right * horizontalMoveSpeed * horizontalMovementMultiplier * Time.deltaTime);
             }
         }else if(horizontalMoveSpeed < 0)
         {
             if (ship.transform.position.x > -7.5)
             {
                 ship.transform.Translate(Vector3.left * horizontalMoveSpeed * horizontalMovementMultiplier * Time.deltaTime * -1);
             }
         }
       }

     //SCROLLING BACKGROUND
     tile1.transform.Translate(Vector2.down * Time.deltaTime * moveSpeed);
     tile2.transform.Translate(Vector2.down * Time.deltaTime * moveSpeed);
      if(tile1.transform.localPosition.y <= -15)
     {
         
          tile1.transform.localPosition = new Vector3(Random.Range(-10.0f, 10.0f) , tile1.transform.localPosition.y + tileHeight, tile1.transform.localPosition.z);
     }
     if (tile2.transform.localPosition.y <= -15)
     {
         tile2.transform.localPosition = new Vector3(Random.Range(-10.0f, 10.0f), tile2.transform.localPosition.y + tileHeight, tile2.transform.localPosition.z);
     }
     //END SCROLLING BACKGROUND

     distanceTraveled += moveSpeed * Time.deltaTime;

    
     //UI STUFF

     speedText.text = "Speed: " + moveSpeed.ToString("N2");
     distanceText.text = "Distance: " + Mathf.Round(distanceTraveled);
     scoreText.text = score.ToString();
 }

Here is "endGameOnDeath()" that is called when the ship's health is <= 0. PreviousGamesLibrary is just a serializable class that holds the score, distance and time of each game which is subsequently stored in a list of PreviousGamesLibrary's to be saved/loaded.

 private void endGameOnDeath()
 {
     
     dataManager.saveNewGame(new PreviousGamesLibrary(score, distanceTraveled, gameTime));

     Invoke("backToMenu", 1);
 }

As you can see I use quite a bit of Time.DeltaTime, including for a delay in my ship shield's recharging - which I also timed and also works flawlessly.

The only static anything in this entire project is dataManager which is a single-tin structure class for managing persistent data (I'm not going to pretend I know exactly what that means, I followed a tutorial lol) but that's the only thing I have declared static in the entire project.

Comment
Add comment · Show 5
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AlwaysSunny · Dec 27, 2016 at 07:03 AM 2
Share

Any chance your Time.timeScale is set to a value besides 1? That would account for this. You can use Time.unscaledDeltaTime to grab an increment which does not care about timeScale.

I don't suppose you're manually calling Update from another function or script? Or have multiple instances of this script, where the timer variable is static?

(I'm guessing you mis-spoke when indicating that you declared the timer variable in the Start method. If you did that, you would not have access to it in the Update method.)

avatar image Ace_Oxide · Dec 28, 2016 at 01:18 AM 0
Share

I just did that to simplify my explanation, the timer float is declared properly and just instantiated in start. I've never used Time.TimeScale, so it should be at it's default value. I have several other things (movement of objects, scrolling background, etc) that all also use Time.deltaTime in their calculations, so is it possible using Time.deltaTime more than once in the update could be causing an issue? And no, there's only one instance of this script.

Odd-ball thing here but in the same update function I spawn entities every 1 second by doing "float spawnTimer += Time.DeltaTime" "if(spawnTimer >=1){ Instantiate(Spawn), spawntimer =0} and THAT spawns a new entity exactly every 1 second according to my stopwatch, but the timer is still wonky.

avatar image AlwaysSunny Ace_Oxide · Dec 28, 2016 at 06:24 AM 0
Share

Are you absolutely certain that the timer variable is not being written to by any other piece of code? That (or a non-one timescale) is the only possible way I can imagine getting an incorrect value under normal circumstances.

Is the project beco$$anonymous$$g non-responsive during play mode? If your frames-per-second are extremely low, that might cause this kind of issue. Are you sure you've made no changes to the project's timestep or timescale? Perhaps you've disabled vsync?

avatar image ScaniX · Dec 28, 2016 at 10:39 AM 1
Share

I'd suggest posting the full code. Just looking at your hints this should work just fine, but probably there is a problem that we cannot see here.

Probably the variable timer is declared static and there somehow is more than one instance of GameController.

avatar image Fobri · Dec 28, 2016 at 08:06 PM 0
Share

Try using fixedupdate and see if it makes any differences.

3 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by AurimasBlazulionis · Dec 28, 2016 at 12:37 PM

It is quite strange. This might be a really weird bug with unity (highly unlikely), it might be some problems with getting time from your PC. You can also have the variable altered from other components. Maybe the timer is static!?

I see one problem is that the timer is declared in start (float timer = 0).

You can try moving to FixedUpdate and use Time.fixedDeltaTime instead.

To not have any problems. Just do something like startTime = Time.time in Start function, and when you update the UI get the time as Time.time - startTime

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by ElijahShadbolt · Dec 28, 2016 at 07:27 AM

I wouldn't use Time.deltaTime to measure time any longer than, like, 1 second, because floats do not have enough digits/figures to be accurately added over hundreds of frames. You're bound to be losing or gaining something due to rounding. Edit: I thought wrong. Ignore that paragraph. Edit 2: If you are running a server with high update frequency (not limited to 60 fps), then perhaps that paragraph may help, so I have kept it in this answer.

I would use Time.time or Time.unscaledTime instead. Or even Time.realtimeSinceStartup. For example,

 float timeAtStart;
 float timer;
 void Start() {
     timeAtStart = Time.time;
     timer = 0;
 }
 void Update() {
     timer = Time.time - timeAtStart;
 }
 
 // at end of game
 (Time.time - timeAtStart).ToString();
 // or just
 timer.ToString();

Note that this is untested.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AlwaysSunny · Dec 28, 2016 at 07:57 AM 1
Share

"floats do not have enough digits/figures to be accurately added over hundreds of frames"

I'm afraid this isn't accurate. If you're talking about hundreds of millions of frames, perhaps. Or in industrial / scientific settings. In the context of video game time management, using a float to accrue deltaTime is 100% fine. Unless you're going to run the application continuously for several consecutive weeks. I'm very confident that this phenomenon is not related the OP's problem.

avatar image
0

Answer by Marc477 · Feb 21 at 04:39 AM

Just want to say that I also had this problem, and the issue WAS what ElijahShadbolt mentioned. You should unstroke that paragraph lol, because that is what actually helped me resolve this.

The thing is that I had this issue on a Unity Server build (linux), so since there are no graphics, the frame rate was something crazy like 50000, which did make the Time.deltaTime extremely small for a float. And as a result, the time was moving much slower than supposed.

I solved this issue with :

 Application.targetFrameRate = 60;

In the Start function of my main manager.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

10 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Time.deltaTime always null 1 Answer

Delay Function (problem with Time.deltaTime) 1 Answer

Does Time.deltaTime not work in FixedUpdate? 1 Answer

How do you Lerp light.color into multiple colors? 2 Answers

How would I make a timer frame independent? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges