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

Unity3D激活场景保存问题:如何保存加载后场景的修改并复现

我懂你现在的困境——你的代码只能记住当前是哪个场景,完全没法还原你在场景里做的那些修改,比如新生成的敌人、摆放的道具对吧?别着急,我们可以通过序列化游戏对象的关键状态数据来解决这个问题,下面是一套完整的实现方案:

解决方案步骤

1. 创建可序列化的保存数据类

首先我们需要定义专门的类来存储每个需要保存对象的关键信息,这个类要标记为[Serializable],这样Unity才能把它转换成可存储的JSON或二进制数据。

using UnityEngine;
using System.Collections.Generic;

[System.Serializable]
public class SavedObjectData
{
    // 预制体唯一标识(用来确定要实例化哪个预制体)
    public string prefabUniqueId;
    // 对象的位置信息
    public Vector3 position;
    // 对象的旋转信息
    public Quaternion rotation;
    // 可扩展:添加你需要保存的其他属性,比如生命值、物品数量等
    // public int currentHealth;
}

[System.Serializable]
public class GameSaveData
{
    // 场景索引(保留你原来的逻辑)
    public int sceneIndex;
    // 所有需要保存的对象数据列表
    public List<SavedObjectData> savedObjects;
}

2. 修改SaveGame方法:收集并保存场景内的修改

现在我们要遍历场景中所有需要保存的对象(建议给这些对象加个Saveable标签方便筛选),把它们的状态数据收集到GameSaveData中,再转成JSON字符串存储起来(这里用PlayerPrefs,大数据量建议用本地文件)。

using UnityEngine.SceneManagement;
using System.Collections.Generic;

public void SaveGame()
{
    GameSaveData saveData = new GameSaveData();
    saveData.sceneIndex = SceneManager.GetActiveScene().buildIndex;
    saveData.savedObjects = new List<SavedObjectData>();

    // 筛选场景中所有标记为"Saveable"的对象
    GameObject[] saveableObjects = GameObject.FindGameObjectsWithTag("Saveable");

    foreach (GameObject obj in saveableObjects)
    {
        SavedObjectData objData = new SavedObjectData();
        // 这里假设预制体的名字是唯一标识,也可以给预制体加自定义组件存Guid更可靠
        objData.prefabUniqueId = obj.name;
        objData.position = obj.transform.position;
        objData.rotation = obj.transform.rotation;

        // 示例:如果对象有自定义状态组件,读取并保存
        // PlayerStatus status = obj.GetComponent<PlayerStatus>();
        // if (status != null)
        // {
        //     objData.currentHealth = status.Health;
        // }

        saveData.savedObjects.Add(objData);
    }

    // 转成JSON字符串并保存
    string saveJson = JsonUtility.ToJson(saveData);
    PlayerPrefs.SetString("FullGameSave", saveJson);
    PlayerPrefs.Save();

    Debug.Log($"游戏保存完成!共记录了 {saveData.savedObjects.Count} 个对象的状态");
}

3. 修改LoadGame方法:读取数据并恢复场景状态

加载时先读取保存的JSON数据,转成GameSaveData,然后加载对应场景,必须等场景加载完成后再实例化对象并恢复状态(用场景加载回调处理异步逻辑)。

// 临时存储保存数据的类成员变量
private GameSaveData _currentLoadedSaveData;

public void LoadGame()
{
    if (!PlayerPrefs.HasKey("FullGameSave"))
    {
        Debug.LogWarning("未找到任何保存数据!");
        return;
    }

    // 读取并解析JSON数据
    string saveJson = PlayerPrefs.GetString("FullGameSave");
    _currentLoadedSaveData = JsonUtility.FromJson<GameSaveData>(saveJson);

    // 加载目标场景,并注册加载完成回调
    SceneManager.LoadScene(_currentLoadedSaveData.sceneIndex);
    SceneManager.sceneLoaded += OnSaveSceneLoaded;
}

private void OnSaveSceneLoaded(Scene scene, LoadSceneMode mode)
{
    // 取消回调注册,避免重复触发
    SceneManager.sceneLoaded -= OnSaveSceneLoaded;

    if (_currentLoadedSaveData == null) return;

    foreach (SavedObjectData objData in _currentLoadedSaveData.savedObjects)
    {
        // 从Resources文件夹加载预制体(大项目建议用Addressable或预制体字典)
        GameObject targetPrefab = Resources.Load<GameObject>(objData.prefabUniqueId);
        if (targetPrefab != null)
        {
            // 实例化对象并恢复状态
            GameObject spawnedObj = Instantiate(targetPrefab, objData.position, objData.rotation);
            // 示例:恢复自定义状态
            // PlayerStatus status = spawnedObj.GetComponent<PlayerStatus>();
            // if (status != null)
            // {
            //     status.Health = objData.currentHealth;
            // }
        }
        else
        {
            Debug.LogWarning($"未找到对应预制体:{objData.prefabUniqueId}");
        }
    }

    Debug.Log($"游戏加载完成!共恢复了 {_currentLoadedSaveData.savedObjects.Count} 个对象");
    _currentLoadedSaveData = null;
}

4. 额外优化建议

  • 预制体标识优化:不要用名字当唯一标识,给每个预制体加一个带Guid的自定义组件,避免重名问题。
  • 场景原有对象修改:如果要保存场景原本就有的对象(比如门的开关状态),给这些对象加SaveableObject组件,在保存时读取组件内的状态,加载时恢复。
  • 存储方式优化:如果保存的数据量大,建议用File.WriteAllText把JSON写到Application.persistentDataPath下的本地文件,比PlayerPrefs更稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:29:57