1

I have a timer in my game which should count the time till the end of the game. I can't figure out how to make it so it will only reset back to 0 when menu scene is active (build index 0).' The second problem is that I don't want it to go back to 0 after every death(scene reload). Have you got any sugestions?

using UnityEngine; 
using UnityEngine.UI; 
using UnityEngine.SceneManagement;

public class Timer : MonoBehaviour { 
public Text TimerText; 
public bool shouldCountTime; 
public float t;

 private void Start()
 {
     if (SceneManager.GetActiveScene().buildIndex != 0)
     {
         shouldCountTime = true;
     }
     else
     {
         shouldCountTime = false;
         t = 0;
     }
     t = Time.deltaTime;
 }
 void Update()
 {
     if (shouldCountTime) {
         t += Time.deltaTime;
     }
     string minutes = ((int)t / 60).ToString();
     string seconds = (t % 60).ToString("f2");
     TimerText.text = minutes + ":" + seconds;
 } 
}
derHugo
  • 83,094
  • 9
  • 75
  • 115
  • you can use the [sceneLoaded](https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager-sceneLoaded.html) event to check what scene is loaded and set your timer according to your need. Also check [dontDestroyOnLoad](https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html) to make elements persistent between scenes. – rustyBucketBay Jun 10 '21 at 09:21
  • Maybe you should checkout [How to pass data between scenes in Unity](https://stackoverflow.com/questions/32306704/how-to-pass-data-between-scenes-in-unity) – derHugo Jun 10 '21 at 09:23

1 Answers1

0

As mentioned you should make it a singleton (meaning only one instance should exist at a time - not speaking about the general (ab)use of having a public static reference ;) )

And use DontDestroyOnLoad in order to keep your object also when the scene is changed and for the resetting use SceneManager.sceneLoaded and check the index of the newly loaded scene like e.g.

public class Timer : MonoBehaviour 
{ 
    // Make sure this text is also not destroyed
    // e.g. make its entire canvas a child of this object
    public Text TimerText; 
    public bool shouldCountTime; 
    public float t;

    // Singleton Pattern -> make sure only one instance exists in your scene
    private static Timer _instance;

    private void Awake()
    {
        // does another instance already exist?
        if(_instance && _instance != this)
        {
            // if so detroy this one
            Destroy(gameObject);
            return;
        }

        // This is the active instance
        _instance = this;

        // Don't destroy this GameObject when a new scene is loaded
        DontDestroyOnload(gameObject);

        // Attach a callback for every new scene that is loaded
        // It is fine to remove a callback that wasn't added so far
        // This makes sure that this callback is definitely only added once
        // usually I do this only as a kind of convention
        SceneManager.sceneLoaded -= OnSceneLoaded;
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    // Will be called every time a scene is loaded
    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        // check the build index
        shouldCountTime = scene.buildIndex != 0;

        // Reset in the main menu
        if(!shouldCountTime)
        {
            Debug.Log("Reset timer", this);
            t = 0;
            TimerText.text = "0:00";
        }
    }

    private void OnDestroy()
    {
        // Even though your object most probably lives during the entire application lifetime
        // again just as a convention always remove callbacks as soon as not needed anymore
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

     void Update()
     {
         // do your calculations only while the value is actually changing
         if (!shouldCountTime) return;

         t += Time.deltaTime;
         var minutes = ((int)t / 60).ToString();
         var seconds = (t % 60).ToString("f2");
         TimerText.text = minutes + ":" + seconds;
     } 
}

If changing the hierarchy (regarding e.g. the Text) is not an option than rather refer to How to pass data between scenes in Unity for alternative solutions for caring over the value.

derHugo
  • 83,094
  • 9
  • 75
  • 115