You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity场景间数据持久化时WorldMapManager重复实例生成问题排查

问题根源与修正方案

核心问题分析

你的代码存在三个关键错误,导致单例失效、地图重复生成:

  1. 单例Instance未赋值:第一个实例创建时,仅调用DontDestroyOnLoad但未将Instance指向当前对象,后续加载场景时新实例检测到Instance为null,不会销毁自身,导致多实例共存。
  2. 事件重复绑定:每次Awake都注册SceneManager.sceneLoaded事件,同一个实例会多次触发回调,可能重复执行地图生成。
  3. 场景加载回调逻辑错误:回到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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 14:05:23