- Home /
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!
Answer by mrpmorris · Jul 24, 2016 at 09:05 AM
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));
That sounds very useful, where can I find out more on how to do that?
Thanks I think I'm going to try and use this method that you've posted, I'm just trying to get your example code to work at the moment, getting a compile error 'A get or set accessor expected' at the moment
Thanks, there are no compile errors now when I build. I can't get the behavior I'm expecting though. I've added some extra code to try and switch the scene when the timer reaches 0
public static TimeSpan TimeLeft
{
get
{
var result = DateTime.UtcNow - TimeStarted;
if (result.TotalSeconds <= 0)
return TimeSpan.Zero;
Scene$$anonymous$$anager.LoadScene("Lose");
return result;
}
}
and I've added
GlobalCountDown.StartCountDown(TimeSpan.FromSeconds(1));
to my void update but I'm not getting any reaction.
Is it easy to see what I'm doing wrong in this case?
Using this method I'm not able to set a time in seconds in my first scene that will carry over to future scene.
The next issue that I'd like to solve is to show the amount of time left in a string so that I can display the time left to the player, I'm not sure how to do this, I've tried some variations using TimeSpan.ToString(); or text.text = TimeSpan.FromSeconds; but I can't get anything to compile without errors, any help or advice with displaying the score would be very helpful
GlobalCountDown.StartCountDown(TimeSpan.FromSeconds(30));
To get the remaining time either
//For seconds, with a leading zero
string timeLeft = GlobalCountDown.TimeRemaining.TotalSeconds().ToString("D2");
// or for $$anonymous$$utes + seconds
string timeLeft = GlobalCountDown.TimeRemaining.ToString("mm:ss");
Then look up the OnGUI method for how to display it on screen
Answer by Arshia001 · Jul 24, 2016 at 09:00 AM
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.