Coroutine not starting due to inactive game object

旧街凉风 提交于 2019-12-12 03:27:15

问题


I'm getting an error message and I'm not exactly sure how to solve. I'm trying to start a countdown after a short period of idleness that then kicks off a second countdown that is paired with a visual warning. As soon as the coroutine kicks on I'm getting this error:

Coroutine couldn't be started because the the game object '_CountdownTimer' is inactive! UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) CountdownTimer:StartPreCountTimer() (at Assets/_Components/_Scripts/CountdownTimer.cs:38) GameManager:CheckUserActivity() (at Assets/_Components/_Scripts/GameManager.cs:68)

What am I missing? Where would I need to set the active state of _CountdownTimer? Thank you!!

GameManager.cs

using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour 
{
    public static GameManager gameManagerInstance = null; // Create Singleton

    public float checkUserActivityInterval;
    public GameObject loader;
    public GameObject countdownTimer;
    private GameObject gameManager; 

    private Vector3 currentMousePosition;
    private Vector3 prevMousePosition;
    private CountdownTimer countdownInstance;
    private Scene currentScene;
    public Color defaultBackgroundColor;                 
    public Object startingScene;

    public static bool userActive;
    public static bool preCountActive;
    public static bool restartWarningActive;

    public static string animalDataFilePathJSON;
    public static string animalDataFilePathTex;

    void Awake ()
    {
        if (CountdownTimer.countdownTimerInstance == null)
            Instantiate(countdownTimer);

        if (gameManagerInstance == null)
            gameManagerInstance = this;
        else if (gameManagerInstance != null)
            Destroy(gameObject);

        DontDestroyOnLoad(gameObject);
    }

    void Start()
    {
        prevMousePosition = Input.mousePosition;
        countdownInstance = countdownTimer.GetComponent<CountdownTimer>(); // Create an instance of CountdownTimer
        InvokeRepeating("CheckUserActivity", 0, checkUserActivityInterval);
        InvokeRepeating("SetPrevMousePosition", 0, checkUserActivityInterval);
    }

    void Update()
    {
        currentScene = SceneManager.GetActiveScene();
        currentMousePosition = Input.mousePosition;
    }

    void CheckUserActivity()
    {
        if (currentScene.name != startingScene.name)
        {
            if (currentMousePosition == prevMousePosition)
            {
                Debug.Log("MOUSE HAS NOT MOVED!!");
                userActive = false;

                if (!userActive && !preCountActive)
                    countdownInstance.StartPreCountTimer();
            }

            if (currentMousePosition != prevMousePosition)
            {
                Debug.Log("MOUSE HAS MOVED!!");
                userActive = true;

                if (preCountActive == true)
                    countdownInstance.RestartPreCountTimer();
            }
        }
    }

    void SetPrevMousePosition()
    {
        prevMousePosition = Input.mousePosition;
    }
}

CountdownTimer.cs

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

public class CountdownTimer : MonoBehaviour
{
    public static CountdownTimer countdownTimerInstance = null; // Create Singleton

    public Object startingScene;
    public GameObject timeOutWarningDialog;
    private GameObject timerDialogBoxInstance;
    private GameObject canvas; 

    private IEnumerator counter;
    private Button stopCountButton;
    private Text timerTextField;

    public float countdownLength;
    public float countdownDelay;
    private float countdownInterval = 1;

    void Awake()
    {
        if (countdownTimerInstance == null)
            countdownTimerInstance = this;
        else if (countdownTimerInstance != null)
            Destroy(gameObject);
        DontDestroyOnLoad(gameObject);
    }

    public void StartPreCountTimer()
    {
        GameManager.preCountActive = true;
        GameManager.restartWarningActive = false;

        counter = RunTimer(countdownDelay); // create new reference to counter
        StartCoroutine(counter);
    }

    public void RestartPreCountTimer()
    {
        GameManager.preCountActive = false;
        StopTimer();
    }

    void ShowRestartWarning()
    {
        GameManager.preCountActive = false;
        GameManager.restartWarningActive = true;

        canvas = GameObject.FindGameObjectWithTag("Canvas");

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

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

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

        if (timerDialogBoxInstance.activeInHierarchy == true)
        {
            counter = RunTimer(countdownLength); // create new reference to counter, resets countdown to countdownLength
            StartCoroutine(counter);
        }
    }

    IEnumerator RunTimer(float seconds)
    {
        float s = seconds;
        while (s > -1)
        {
            if (GameManager.restartWarningActive == true)
                if (timerTextField != null)
                    timerTextField.text = s.ToString();

            yield return new WaitForSeconds(countdownInterval);
            s -= countdownInterval;
        }

        if (s == -1)
        {
            if (GameManager.restartWarningActive == true)
                RestartGame();
        }
    }

    void StopTimer()
    {
        Debug.Log("Restart Cancelled");
        StopCoroutine(counter);
        Destroy(timerDialogBoxInstance);
    }

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

回答1:


I think I know where your error is. When you create an instance of the countdownTimer. You have to store a reference to it in order to get the underlying CountdownTimer class.

Try doing this, in your GameManager Class

private GameObject countDownTimerInstance;

Awake()

countDownTimerInstance = Instantiate(countdownTimer);

and in the Start() do,

countdownInstance = countdownTimerInstance.GetComponent<CountdownTimer>();

I think the problem was you were directly accessing the prefab's getComponent() instead of the instantiated gameObject's CountdownTimer!.



来源:https://stackoverflow.com/questions/45135385/coroutine-not-starting-due-to-inactive-game-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!