Unity单例ScoreKeeper切换游戏场景时抛出NullReferenceException求助
解决调用ScoreKeeper.ResetScore时的NullReferenceException异常
关键排查点
确认LevelManager调用时机
不要在Awake()中直接调用ResetScore,场景加载时LevelManager可能比DontDestroyOnLoad的ScoreKeeper实例先完成初始化。把调用逻辑移到Start()方法,或者通过SceneManager.sceneLoaded回调触发,确保场景完全加载后再访问单例。检查单例实现的严谨性
确保ScoreKeeper的单例代码没有逻辑漏洞,示例正确实现:private static ScoreKeeper _instance; public static ScoreKeeper Instance => _instance; void Awake() { if (_instance != null) { Destroy(gameObject); return; } _instance = this; DontDestroyOnLoad(gameObject); }注意:后续场景无需再放置ScoreKeeper预制体——DontDestroyOnLoad会保留第一个实例,重复放置会导致新实例被销毁,如果LevelManager引用了被销毁的场景内实例,就会触发空引用。
排查ResetScore方法内部
空引用可能来自方法内未初始化的变量(比如分数显示UI未赋值)。在方法内添加日志排查:public void ResetScore() { Debug.Log($"ResetScore triggered by: {gameObject.name}"); if (scoreDisplayText == null) { Debug.LogError("scoreDisplayText未在ScoreKeeper中赋值"); return; } // 重置分数逻辑 currentScore = 0; scoreDisplayText.text = currentScore.ToString(); }验证LevelManager的引用方式
LevelManager必须通过ScoreKeeper.Instance访问单例,禁止使用FindObjectOfType<ScoreKeeper>()或场景内直接拖拽引用——后者会在场景切换后指向已销毁的实例。
快速验证步骤
- 在LevelManager调用
ResetScore前添加日志:Debug.Log($"ScoreKeeper实例状态: {ScoreKeeper.Instance}");,确认实例不为空。 - 在ScoreKeeper的
Awake()和OnDestroy()中添加日志,追踪实例的创建/销毁时机,对比LevelManager的调用时机是否冲突。 - 移除所有后续场景中的ScoreKeeper预制体,只保留初始场景(如MainMenu)中的实例,测试是否仍报错。
内容的提问来源于stack exchange,提问作者Maxence Hermand
相关产品推荐
相关产品推荐

