Unity场景间数据持久化时WorldMapManager重复实例生成问题排查
问题根源与修正方案
核心问题分析
你的代码存在三个关键错误,导致单例失效、地图重复生成:
- 单例Instance未赋值:第一个实例创建时,仅调用
DontDestroyOnLoad但未将Instance指向当前对象,后续加载场景时新实例检测到Instance为null,不会销毁自身,导致多实例共存。 - 事件重复绑定:每次
Awake都注册SceneManager.sceneLoaded事件,同一个实例会多次触发回调,可能重复执行地图生成。 - 场景加载回调逻辑错误:回到
WorldMap场景时,错误销毁脚本组件而非多余GameObject,且未判断地图是否已初始化,导致重复生成。
修正后的完整代码
using UnityEngine; using UnityEngine.SceneManagement; public class WorldMapManager : MonoBehaviour { public static WorldMapManager Instance { get; private set; } public static int _mapSizeX = 4; public static int _mapSizeY = 4; public static int _playerScore; public static int _playerCells; public static int _enemyScore; public static int _enemyCells; public static GameObject[,] _map; public static GameObject _startingPoint; public static Vector2Int _playerBase; private bool _isMapInitialized = false; void Awake() { // 单例逻辑:确保仅存在一个实例 if (Instance != null) { Destroy(gameObject); return; } Instance = this; DontDestroyOnLoad(gameObject); // 只注册一次事件,避免重复绑定 SceneManager.sceneLoaded += OnLevelFinishedLoading; } void OnDestroy() { // 销毁时取消事件绑定,防止内存泄漏 SceneManager.sceneLoaded -= OnLevelFinishedLoading; } // 初始化地图(仅执行一次) public void InitMap() { if (_isMapInitialized) return; // 你的地图生成逻辑写在这里 Debug.Log("地图初始化完成"); _isMapInitialized = true; } void OnLevelFinishedLoading(Scene scene, LoadSceneMode mode) { if (scene.name == "WorldMap") { // 仅单例实例执行地图初始化(且仅第一次执行) if (Instance == this) { InitMap(); } } } }
关键改动说明
- 单例赋值:在
Awake的else分支添加Instance = this;,确保第一个实例被正确标记为单例,后续新实例会被直接销毁。 - 事件生命周期管理:在
OnDestroy中取消事件绑定,避免重复触发和内存泄漏。 - 地图初始化控制:添加
_isMapInitialized标记,确保地图仅在第一次加载场景时生成,后续返回场景不再重复执行。 - 回调逻辑简化:场景加载回调中仅判断当前实例是否为单例,避免多余的销毁逻辑,因为单例已经保证只有一个实例存活。
额外注意事项
- 确保
WorldMap场景中只有一个挂载WorldMapManager的GameObject,避免场景初始化时就存在多个实例。 - 如果需要重置地图状态(比如重新开始游戏),可以添加一个
ResetMap()方法,重置_isMapInitialized和相关静态变量后重新调用InitMap()。
内容的提问来源于stack exchange,提问作者Yakuman
相关产品推荐
相关产品推荐

