Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question my timer does not reset when I play the scene again

Discussion in 'Scripting' started by justinmed, Mar 31, 2024.

  1. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    For some reason when my countdown timer hits zero it will not reset when I play the scene again and I cannot figure out why. I put some code in there to have it continue across scenes, but I do not think that should be where the issue might be. Any help is greatly appreciated.

    Here is the script for it.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using TMPro;
    6. using UnityEngine.SceneManagement;
    7.  
    8. public class Timer : MonoBehaviour
    9. {
    10.  
    11.     public TextMeshProUGUI timerText;
    12.     public float remainingTime;
    13.     public bool timerOn;
    14.     public bool timeIsRunning = true;
    15.  
    16.     private void Start()
    17.     {
    18.         if (PlayerPrefs.HasKey("timeValue"))
    19.         {
    20.             remainingTime = PlayerPrefs.GetFloat("timeValue");
    21.         }
    22.      
    23.         timerOn = true;
    24.     }
    25.  
    26.  
    27.     // Update is called once per frame
    28.     void Update()
    29.     {
    30.         if (remainingTime > 0)
    31.         {
    32.             remainingTime -= Time.deltaTime;
    33.             updateTimer(remainingTime);
    34.             PlayerPrefs.SetFloat("timeValue", remainingTime);
    35.             updateTimer(remainingTime);
    36.         }
    37.         else
    38.         {
    39.             remainingTime = 0;
    40.             timerOn = false;
    41.         }
    42.  
    43.         void updateTimer(float DisplayTime)
    44.  
    45.         {
    46.             DisplayTime -= 1;
    47.             int minutes = Mathf.FloorToInt(remainingTime / 60);
    48.             int seconds = Mathf.FloorToInt(remainingTime % 60);
    49.             timerText.text = string.Format("{0:00}:{1:00}", minutes, seconds);
    50.         }
    51.  
    52.      
    53.          
    54.     }
    55. }
     
  2. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    Okay so it is something to do with keeping the time value across scenes. It is something in this part of the code, I deleted this part just to see what would happen and it worked just fine.

    Code (CSharp):
    1. private void Start()
    2.     {
    3.         if (PlayerPrefs.HasKey("timeValue"))
    4.         {
    5.             remainingTime = PlayerPrefs.GetFloat("timeValue");
    6.         }
    7.        
    8.         timerOn = true;
    9.     }
     
  3. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    So, I found that I am missing some correct way to delete the key when the timer hits zero or the scene or application is voided. But I have still not managed to get it right. I tried this,
    Code (CSharp):
    1.  void OnApplicationQuit()
    2.  
    3.         {
    4.             PlayerPrefs.DeleteKey("timeValue");
    5.         }
    and this

    Code (CSharp):
    1.  void resetTimer()
    2.         {
    3.             remainingTime = 0;
    4.             updateTimer(remainingTime);
    5.             PlayerPrefs.DeleteKey("timeValue");
    6.            
    7.            
    8.         }
    Both were, of course, unsuccessful.
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,159
    If you want it to persist across scenes, make it a DontDestroyOnLoad game object, rather than abusing PlayerPrefs.
     
  5. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    Yeah that is something to try.
     
  6. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    So far, I have not been able to get a simple DontDestroy script to work. I was watching tutorials and it said that this should work in a basic sense.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class DontDestroy : MonoBehaviour
    7. {
    8.     private void Awake()
    9.     {
    10.         DontDestroyOnLoad(gameObject);
    11.     }
    12. }
    13.  
     
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,159
    Did you remember to put it on the correct game object?
     
  8. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    I put it on the TMPro Text that the timer is on. I did get the timer to delete its key after zero by adding another if statement that I will show, but now the timer can only be reset if it hits zero rather than when the scene is quit with OnApplicationQuit. The DontDestroyOnLoad would be useful if it was working though. I could really use it for a scoring system that maintains score across scenes as each point gained switches to a new scene.

    Code (CSharp):
    1.  void Update()
    2.     {
    3.         if (remainingTime > 0)
    4.         {
    5.             remainingTime -= Time.deltaTime;
    6.             updateTimer(remainingTime);
    7.             PlayerPrefs.SetFloat("timeValue", remainingTime);
    8.             updateTimer(remainingTime);
    9.         }
    10.         else
    11.         {
    12.             remainingTime = 0;
    13.             timerOn = false;
    14.         }
    15.  
    16.         if (remainingTime < 0)
    17.         {
    18.             remainingTime = 0;
    19.             updateTimer(remainingTime);
    20.             PlayerPrefs.DeleteKey("timeValue");
    21.            
    22.         }
    23.        
     
  9. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    When I try:
    Code (CSharp):
    1. void OnApplicationQuit()
    2.  
    3.         {
    4.             PlayerPrefs.DeleteKey("timeValue");
    it leaves the OnApplicationQuit greyed out and of course does nothing.
     
  10. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    I tried this,
    Code (CSharp):
    1. UnityEditor.EditorApplication.isPlaying = false;
    2.         PlayerPrefs.DeleteKey("timeValue");
    and it deleted the key on application quit, but the scene quits on its own a second into beginning, so if I could figure out how to tell it that upon close delete the key that would work, but strangely void OnApplicationQuit() has not been working.
     
  11. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    I was just putting void OnApplicationQuit into the wrong area of the script. It just worked. Now to try and get the DontDestroyonLoad to work for the score, I am set.
     
  12. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,159
    Yes you've been using local/nested methods in your script. I would avoid doing that unless you understand what you're doing with them.

    DontDestroyOnLoad does work and is a pretty fundamental part of Unity, so there is something you're doing wrong on your end.
     
  13. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    79
    For time it seems straight forward enough. But for the score part, I found out my issue was that DontDestroyOnLoad only works if it is at root level on the scene and not under an object in a Canvas, which in order to have it at root level, the panel BG removes the text from sight. So, I am not sure if there is a work around for that or not. It would be nice if there was.