countdown to persist through scenes

Hi,

I have a countdown clock in my game which I want to run through multiple scenes while keeping the time from the previous scenes. I have a timer coded, and I have a DontDestroyOnLoad added.

I’ve tried putting the code into each scene but it will restart the countdown, I have also tried only adding the code to the first scene where the timer starts but then the code and the display won’t carry over to the next scene.

My code is attached to a text element that is inside the canvas, looking into it, this may be part of my issue but I’m not sure how I’m able to get around it.

Here is my code;

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class CountDown : MonoBehaviour {

	public GameObject timeTF;
	public GameObject alertReference;

	void Start () {
		DontDestroyOnLoad(transform.gameObject);
		timeTF.GetComponent<Text>().text = "120";
		InvokeRepeating("ReduceTime", 1, 1);
	}
	void ReduceTime()
	{
		if (timeTF.GetComponent<Text>().text == "1")
		{
			SceneManager.LoadScene("lose");
		}

		timeTF.GetComponent<Text>().text = (int.Parse(timeTF.GetComponent<Text>().text) - 1).ToString();
	}    
}

And here is the hierarchy of the scene that it’s been placed into;

There is mention of DontDestroyOnLoad not working on child, and only on parents, I don’t understand the limitations of it and would appreciate some help and advise, either on how to get the current method I’m using to work, or a different way to carry a time between different scenes. Thanks!

Why not have a static property on a static class that keeps the current timer value and is reset when you start the game on the first level?

public static class GlobalCountDown
{
    static DateTime TimeStarted;
    static TimeSpan TotalTime;

    public static void StartCountDown(TimeSpan totalTime)
    {
        TimeStarted = DateTime.UtcNow;
        TotalTime = totalTime;
    }

    public static TimeSpan TimeLeft
    {
        get
        {
            var result = TotalTime - (DateTime.UtcNow - TimeStarted);
            if (result.TotalSeconds <= 0)
                return TimeSpan.Zero;
            return result;
        }
    }
}

When your first level starts just do this

GlobalCountDown.StartCountDown(TimeSpan.FromMinutes(5));

I’d put separate timers (logic, script, graphics, everything) into every scene. You could have a script with the express purpose of carrying information over to the next scene. Something like this:

using UnityEngine;
using System.Collections;

public class InterSceneState : MonoBehaviour
{
    public float TimeRemaining;
}

Then, when one scene is to unload and the next is to load, you could do this:

var GO = new GameObject("State");
var ISS = GO.AddComponent<InterSceneState>();
ISS.TimeRemaining = m_timeRemaining; // with m_timeRemaining being whatever way you're keeping the remaining time
DontDestroyOnLoad(GO);
Application.LoadLevel(...);

Then, in the timer script’s start function which runs when the next scene is loaded:

var GO = GameObject.Find("State");
var ISS = GO.GetComponent<InterSceneState>();
m_timeRemaining = ISS.TimeRemaining;
Destroy(GO);

And there you have it.