StopCoroutine 调用后文本对象更新
Text object updating after StopCoroutine called
我似乎无法找出为什么会出现此错误。
MissingReferenceException: 'Text' 类型的对象已被销毁,但您仍在尝试访问它。
您的脚本应该检查它是否为空,或者您不应该销毁该对象。
这似乎是在调用 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);
}
}
当您调用 Destroy(timerDialogBoxInstance);
时,也会破坏 countdownText
和 countdownTextTarget
(您在 StopTimerButton()
和 RunTimer()
中执行)。
您应该检查内部 RunTimer()
(在访问 Text 对象之前)以查看该对象是否已被销毁,如果是,请提前退出。
您可能还想在销毁其父转换后将变量设置为空。
我似乎无法找出为什么会出现此错误。
MissingReferenceException: 'Text' 类型的对象已被销毁,但您仍在尝试访问它。 您的脚本应该检查它是否为空,或者您不应该销毁该对象。
这似乎是在调用 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);
}
}
当您调用 Destroy(timerDialogBoxInstance);
时,也会破坏 countdownText
和 countdownTextTarget
(您在 StopTimerButton()
和 RunTimer()
中执行)。
您应该检查内部 RunTimer()
(在访问 Text 对象之前)以查看该对象是否已被销毁,如果是,请提前退出。
您可能还想在销毁其父转换后将变量设置为空。