我似乎无法追查为什么会发生此错误..
MissingReferenceException:“Text”类型的对象已被销毁,但您仍在尝试访问它。 您的脚本应该检查它是否为null或者您不应该销毁该对象。
在调用StopTimerButton函数之后,似乎正在发生这种情况。之后,似乎我的RunTimer IEnumerator仍在运行。即使我在StopTimerButton()中调用StopCoroutine,RunTimer中的行 countdownTextTarget.text = s.ToString(); 仍然会被调用。这是为什么?需要一些帮助来追踪逻辑中断。谢谢!
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;
public float preCountdownLength;
public float countdownLength;
private GameObject timerDialogBoxInstance;
private GameObject countdownText;
private Text countdownTextTarget;
private GameObject canvas;
private IEnumerator warningCounter;
private IEnumerator preCounter;
private Button stopCountButton;
private float countdownInterval = 1.0f;
private bool preCountActive;
private bool warningCountActive;
void Awake()
{
ResetCountStates();
if (countdownTimerInstance == null)
countdownTimerInstance = this;
else if (countdownTimerInstance != null)
Destroy(gameObject);
DontDestroyOnLoad(gameObject);
}
void Update()
{
bool userActive = GameManager.userActive;
bool onIntroScreen = GameManager.onIntroScreen;
if (!userActive && !onIntroScreen && !preCountActive)
{
StartPreCountTimer(preCountdownLength);
}
else if (userActive && !onIntroScreen && preCountActive)
{
StopPreCountTimer();
}
}
void StartPreCountTimer(float length)
{
preCountActive = true;
preCounter = RunTimer(length);
StartCoroutine(preCounter);
Debug.Log("PreCount Started");
}
void StopPreCountTimer()
{
preCountActive = false;
StopCoroutine(preCounter);
Debug.Log("PreCount Stopped");
}
void WarningDialog(float length)
{
preCountActive = false;
warningCountActive = true;
canvas = GameObject.FindGameObjectWithTag("Canvas");
timerDialogBoxInstance = Instantiate(timeOutWarningDialog); // instantiate timeout warning dialog
if (timerDialogBoxInstance !=null)
{
timerDialogBoxInstance.transform.SetParent(canvas.transform, false);
timerDialogBoxInstance.SetActive(true);
countdownText = GameObject.FindGameObjectWithTag("CountdownText");
countdownTextTarget = countdownText.GetComponent<Text>();
stopCountButton = timerDialogBoxInstance.GetComponentInChildren<Button>(); // get reference to keep playing button
stopCountButton.onClick.AddListener(StopTimerButton); // add button listener
}
if (warningCountActive && !preCountActive)
{
warningCounter = RunTimer(length); // create new reference to counter, resets countdown to countdownLength
StartCoroutine(warningCounter);
}
}
IEnumerator RunTimer(float seconds)
{
// PRECOUNT TIMER
if (!warningCountActive)
{
float s = seconds;
while (s > 0)
{
yield return new WaitForSeconds(countdownInterval);
s -= countdownInterval;
Debug.Log("PreCount: " + s);
}
if (s == 0)
{
preCountActive = false;
warningCountActive = true;
WarningDialog(countdownLength);
}
}
// WARNING DIALOG TIMER
if (!preCountActive && warningCountActive)
{
float s = seconds;
while (s > 0)
{
yield return new WaitForSeconds(countdownInterval);
countdownTextTarget.text = s.ToString();
s -= countdownInterval;
Debug.Log("WarningCountdown: " + s);
}
if (s == 0)
{
StopCoroutine(warningCounter);
if (timerDialogBoxInstance)
Destroy(timerDialogBoxInstance);
RestartGame();
}
}
}
void StopTimerButton()
{
warningCountActive = false;
StopCoroutine(warningCounter);
if (timerDialogBoxInstance)
{
Destroy(timerDialogBoxInstance);
}
Debug.Log("Restart Cancelled");
}
void ResetCountStates()
{
preCountActive = false;
warningCountActive = false;
}
void RestartGame()
{
ResetCountStates();
SceneManager.LoadScene(startingScene.name);
}
}
答案 0 :(得分:2)
当您致电Destroy(timerDialogBoxInstance);
并同时销毁countdownText
和countdownTextTarget
(您在StopTimerButton()
和RunTimer()
内执行此操作时)。
您应该在RunTimer()
内检查(在访问Text对象之前)以查看对象是否已被销毁,如果是,请提前退出。
您可能还希望在销毁父变换后将变量设置为null。