Search code examples
c#unity-game-enginecountercountdown

Reset countdown time after StopCoroutine


I'm having trouble figuring out how to reset the inactivity countdown of my timer. I'm using a coroutine to take care of the countdown and then stopping the countdown via button press using StopCoroutine. But when the countdown dialog reinstatiates and starts back up again (after inactivity) the count starts at the value it left off on previously. How do I reset the count to start at the full countdown amount each time my counter instantiates?

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

public class GameManager : MonoBehaviour 
{
    public static GameManager gameManagerInstance = null; // Create Singleton
    public Color defaultBackgroundColor;                 
    public Object startingScene;
    public GameObject timeOutWarningDialog;

    private float countdownLength = 15;
    private float countdownDelay = 5;
    private float countdownInterval = 1;
    private IEnumerator counter;
    private Button stopCountButton;
    private Text timerTextField;
    private Vector3 prevMousePosition;
    private Scene currentScene;
    private GameObject gameManager;
    private GameObject canvas;
    private GameObject timerInstance;

    void Awake()
    {
        if (gameManagerInstance == null)
            gameManagerInstance = this;
        else if (gameManagerInstance != null)
            Destroy(gameObject);
        DontDestroyOnLoad(gameObject);
        gameManager = GameObject.FindGameObjectWithTag("GameManager");
    }

    void Start()
    {
        counter = RunTimer(countdownLength);
        prevMousePosition = Input.mousePosition;
        currentScene = SceneManager.GetActiveScene();
    }

    void Update()
    {
        if (Input.anyKeyDown || Input.mousePosition != prevMousePosition)
        {
            currentScene = SceneManager.GetActiveScene();

            if (currentScene.name != startingScene.name)
                StartPreCountTimer();
                if (timeOutWarningDialog != null)
                    timeOutWarningDialog.SetActive(false);
        }
        prevMousePosition = Input.mousePosition;
    }

    // GAME TIMER

    public void StartPreCountTimer()
    {
        CancelInvoke();
        if (GameObject.FindGameObjectWithTag("Timer") == null)
            Invoke("ShowRestartWarning", countdownDelay);
    }

    void ShowRestartWarning()
    {
        canvas = GameObject.FindGameObjectWithTag("Canvas");

        timerInstance = Instantiate(timeOutWarningDialog); // instantiate timeout warning dialog
        timerInstance.transform.SetParent(canvas.transform, false);
        timerInstance.SetActive(true);

        Text[] textFields = timerInstance.GetComponentsInChildren<Text>(true); // get reference to timer textfields
        timerTextField = textFields[1]; // access and assign countdown textfield

        stopCountButton = timerInstance.GetComponentInChildren<Button>(); // get reference to keep playing button
        stopCountButton.onClick.AddListener(StopTimer); // add button listener

        if (timerInstance.activeSelf == true)
            StartCoroutine(counter);
    }

    IEnumerator RunTimer(float seconds)
    {
        float s = seconds;
        while (s > 0)
        {
            if (timerTextField != null)
                timerTextField.text = s.ToString();
            yield return new WaitForSeconds(countdownInterval);
            s -= 1;
        }

        if (s == 0)
        {
            RestartGame();
        }
    }

    void StopTimer()
    {
        StopCoroutine(counter);
        Destroy(timerInstance);
    }

    void RestartGame()
    {
        SceneManager.LoadScene(startingScene.name);
    }
}

Solution

  • You need to assign a new reference to counter if you want to reset (it's not properly a reset, but just a new coroutine) the code inside the coroutine.

    I.E.:

    void StopTimer() {
        StopCoroutine(counter);
        counter = RunTimer(countdownLength);
        Destroy(timerInstance);
    }