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

Unity游戏场景状态保存实现:重访场景保留离开时状态

Unity场景保持离开时状态的实现方案

一、避免卸载场景(最直接方案)

如果内存允许,切换场景时不卸载原场景,仅禁用它;返回时重新激活即可保留所有状态。

实现代码

// 切换场景并保留当前场景(叠加加载)
public void SwitchSceneKeepCurrent(string targetSceneName)
{
    // 以叠加模式加载目标场景
    SceneManager.LoadScene(targetSceneName, LoadSceneMode.Additive);
    // 切换活跃场景到新场景,同时禁用原场景
    Scene currentScene = SceneManager.GetActiveScene();
    SceneManager.SetActiveScene(SceneManager.GetSceneByName(targetSceneName));
}

// 返回之前的场景
public void ReturnToPreviousScene(string previousSceneName)
{
    Scene targetScene = SceneManager.GetSceneByName(previousSceneName);
    if (targetScene.isLoaded)
    {
        // 卸载当前活跃场景
        SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene());
        // 激活之前保留的场景
        SceneManager.SetActiveScene(targetScene);
    }
}

注意:此方法适合中小体量场景,缺点是会增加内存占用。

二、序列化存储场景状态(适合资源占用高的场景)

通过序列化保存场景中关键对象的状态(敌人存活、物品收集等),重新加载场景时读取并恢复。

1. 定义状态数据类

[Serializable]
public class SceneStateData
{
    public string sceneName;
    public Dictionary<string, bool> enemyAliveStatus; // Key:敌人唯一ID,Value:是否存活
    public Dictionary<string, bool> itemCollectedStatus; // Key:物品唯一ID,Value:是否已收集
    // 可扩展其他状态:门的开关、机关状态等
}

需给Enemy、CollectibleItem等对象添加UniqueID字段(Inspector手动赋值或自动生成)。

2. 离开场景前保存状态

public void SaveSceneState(string sceneName)
{
    SceneStateData state = new SceneStateData();
    state.sceneName = sceneName;
    state.enemyAliveStatus = new Dictionary<string, bool>();
    state.itemCollectedStatus = new Dictionary<string, bool>();

    // 收集敌人状态
    Enemy[] enemies = FindObjectsOfType<Enemy>();
    foreach (Enemy enemy in enemies)
    {
        state.enemyAliveStatus[enemy.UniqueID] = enemy.isAlive;
    }

    // 收集物品状态
    CollectibleItem[] items = FindObjectsOfType<CollectibleItem>();
    foreach (CollectibleItem item in items)
    {
        state.itemCollectedStatus[item.UniqueID] = item.isCollected;
    }

    // 序列化保存到PlayerPrefs(也可改用文件、数据库)
    string json = JsonUtility.ToJson(state);
    PlayerPrefs.SetString($"SceneState_{sceneName}", json);
    PlayerPrefs.Save();
}

3. 加载场景后恢复状态

public void LoadSceneState(string sceneName)
{
    if (!PlayerPrefs.HasKey($"SceneState_{sceneName}"))
        return;

    string json = PlayerPrefs.GetString($"SceneState_{sceneName}");
    SceneStateData state = JsonUtility.FromJson<SceneStateData>(json);

    // 恢复敌人状态
    Enemy[] enemies = FindObjectsOfType<Enemy>();
    foreach (Enemy enemy in enemies)
    {
        if (state.enemyAliveStatus.TryGetValue(enemy.UniqueID, out bool isAlive))
        {
            enemy.isAlive = isAlive;
            enemy.gameObject.SetActive(isAlive);
        }
    }

    // 恢复物品状态
    CollectibleItem[] items = FindObjectsOfType<CollectibleItem>();
    foreach (CollectibleItem item in items)
    {
        if (state.itemCollectedStatus.TryGetValue(item.UniqueID, out bool isCollected))
        {
            item.isCollected = isCollected;
            item.gameObject.SetActive(!isCollected); // 已收集物品隐藏
        }
    }
}

三、全局状态管理器(内存内持久化)

创建单例状态管理器,用DontDestroyOnLoad标记使其跨场景保留,负责存储所有场景的运行时状态。

实现代码

public class SceneStateManager : MonoBehaviour
{
    public static SceneStateManager Instance;
    private Dictionary<string, SceneStateData> _allSceneStates = new Dictionary<string, SceneStateData>();

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    // 保存指定场景状态
    public void SaveSceneState(string sceneName)
    {
        SceneStateData state = new SceneStateData();
        state.sceneName = sceneName;
        // 此处复用前面的状态收集逻辑
        _allSceneStates[sceneName] = state;
    }

    // 获取指定场景状态
    public SceneStateData GetSceneState(string sceneName)
    {
        _allSceneStates.TryGetValue(sceneName, out SceneStateData state);
        return state;
    }
}

说明:该方案状态仅存于内存,游戏退出后需额外写入持久化存储(如PlayerPrefs)才能保留。

四、方案选择建议

  • 内存充足时优先用场景叠加加载,无需额外状态逻辑;
  • 内存紧张或需要跨游戏会话保留状态时,用序列化存储方案;
  • 仅需运行时跨场景保留状态,用全局状态管理器。

内容的提问来源于stack exchange,提问作者Yui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:05:24