Unity调用外部Timer脚本变量时出现NullReferenceException报错问询
问题原因及修复方案
核心报错原因
- 直接通过
Timer类名访问非静态成员:你定义的timerIsRunning、timeRemaining都是Timer类的实例字段,没有加static修饰,必须先获取场景中挂载了Timer脚本的组件实例才能访问,直接用类名访问要么无法通过编译,要么就是你强行给字段加了static但没有绑定实际的组件实例,导致访问空对象抛出异常。 - 额外逻辑问题:代码中
while (Timer.timerIsRunning == true){}是空死循环,Unity的所有帧逻辑、Update方法都运行在主线程,死循环会直接卡住主线程,Timer的计时逻辑永远不会执行,程序会直接无响应。
修复步骤
1. 调整Timer脚本,增加全局访问入口
给Timer加单例实现,保证全局可以安全访问到场景中唯一的Timer实例:
using UnityEngine; public class Timer : MonoBehaviour { // 全局单例入口 public static Timer Instance { get; private set; } public float timeRemaining = 10; public bool timerIsRunning = false; private void Awake() { // 单例赋值,保证场景中只有一个Timer组件 if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } } void Update() { if (timerIsRunning) { if (timeRemaining > 0) { timeRemaining -= Time.deltaTime; } else { timeRemaining = 0; timerIsRunning = false; } } } // 封装启动计时器的公共方法,避免外部直接修改字段 public void StartTimer(float duration) { timeRemaining = duration; timerIsRunning = true; } }
2. 修改报错的CMDelay方法,用协程替代死循环等待
死循环会卡住主线程,用Unity协程实现等待逻辑,不会阻塞主线程运行:
// 原CMDelay改为启动协程 public void CMDelay(int delay) { StartCoroutine(CMDelayCoroutine(delay)); } // 协程实现计时等待逻辑 private IEnumerator CMDelayCoroutine(int delay) { terminalInputText.enabled = false; // 通过单例调用启动计时器方法 Timer.Instance.StartTimer(delay); // 等待计时器结束,不会卡主线程 yield return new WaitUntil(() => !Timer.Instance.timerIsRunning); terminalInputText.enabled = true; }
注意事项
- 必须把
Timer脚本挂载到场景中始终激活的GameObject上,否则单例Instance会为空,还是会抛出空引用异常。 - 场景中只能有一个挂载了
Timer脚本的对象,避免单例被覆盖。
内容的提问来源于stack exchange,提问作者blue44
相关产品推荐
相关产品推荐

