【问题标题】:Coroutine not starting due to inactive game object由于不活动的游戏对象,协程未启动
【发布时间】:2017-12-21 11:14:31
【问题描述】:

我收到一条错误消息,但我不确定如何解决。我试图在短暂的空闲时间后开始倒计时,然后开始第二次倒计时,并伴有视觉警告。一旦协程启动,我就会收到此错误:

无法启动协程,因为游戏对象“_CountdownTimer”处于非活动状态! UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) CountdownTimer:StartPreCountTimer() (在 Assets/_Components/_Scripts/CountdownTimer.cs:38) GameManager:CheckUserActivity()(在 Assets/_Components/_Scripts/GameManager.cs:68)

我错过了什么?我需要在哪里设置 _CountdownTimer 的活动状态?谢谢!!

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);
    }
}

【问题讨论】:

  • 您将倒计时脚本附加到的游戏对象在哪里?检查它是否处于活动状态。
  • @SurajS CountdownTimer.cs 附加到 _CountdownTimer 预制件上,该预制件在 GameManager.cs 在 Awake 上被实例化。
  • _CountdownTimer 的父级是否在任何时候都处于非活动状态?如果是这样,您必须使用 timerInstance.activeInHierarchy 而不是 timerInstance.activeSelf 才能正常工作
  • @SurajS 错误实际上是在调用 ShowRestartWarning 函数之前出现的。当协程第一次被调用时,它首先在 StartPreCountTimer 中被调用。
  • 在编辑器中实例化预制件后向我们展示您的层次结构树。@greyBow

标签: c# unity3d coroutine


【解决方案1】:

我想我知道你的错误在哪里。当您创建countdownTimer 的实例时。您必须存储对它的引用才能获得底层的 CountdownTimer 类。

在您的 GameManager 类中尝试这样做

private GameObject countDownTimerInstance;

唤醒()

countDownTimerInstance = Instantiate(countdownTimer);

Start() 中做,

countdownInstance = countdownTimerInstance.GetComponent<CountdownTimer>();

我认为问题在于您直接访问 prefab 的 getComponent() 而不是 实例化的 gameObject 的 CountdownTimer!。

【讨论】:

  • 我应该在 GameManager 类还是 CountdownTimer 类中进行这些更改?
  • GameManager 类@greyBow
猜你喜欢
  • 1970-01-01
  • 2017-11-14
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多