You need to enable JavaScript to run this app. Unity C# ScriptableObject修改内容无法保存到磁盘问题求助
优惠活动
大模型
产品
解决方案
定价
更多

Unity C# ScriptableObject修改内容无法保存到磁盘问题求助

问题原因
  • 缺少显式序列化标记:List<Textures> textures字段未显式添加[SerializeField],特殊场景下Unity会跳过该字段的序列化,导致重启后数据被重置。
  • 编辑器API调用不规范:EditorUtility.SetDirty、AssetDatabase.SaveAssets等编辑器专属API没有加条件编译限制,如果脚本放在Runtime目录下会触发编译错误,直接导致序列化失败;且在OnValidate、OnDisable、OnDestroy中频繁强制保存资源,会在序列化未完成时写入错误数据,最终覆盖你的修改。
  • 自动保存逻辑打乱默认时序:你在生命周期函数中强制调用AssetDatabase.SaveAssets会打乱Unity自身的资源保存逻辑,尤其在编辑器退出时调用该接口,大概率会将未完成序列化的空数据写入资源文件,直接导致修改丢失。
解决方案
  1. 给所有需要持久化的字段显式添加[SerializeField]标记,确保Unity正确序列化内容。
  2. 所有编辑器专属API用#if UNITY_EDITOR条件编译包裹,避免运行时编译报错。
  3. 移除生命周期函数中不必要的AssetDatabase.SaveAssets调用,Unity会在你手动保存项目(Ctrl+S)或正常退出时自动保存所有标记为Dirty的资源。
  4. 调整OnValidate逻辑,仅在race字段实际修改时触发列表重置,避免误覆盖已编辑的内容。
修改后参考代码
using System;
using System.Collections.Generic;
using UnityEngine;
// 编辑器命名空间用条件编译引入
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace ModelManager
{
    [CreateAssetMenu(fileName = "New Texture Set", menuName = "Model Manager/New Texture Set")]
    public class TextureSetSO :  ScriptableObject
    {
        [SerializeField]
        public RaceModelSO race;
        // 显式加SerializeField确保序列化
        [SerializeField]
        public List<Textures> textures;
        // 非序列化私有字段加NonSerialized标记,避免不必要的序列化尝试
        [NonSerialized]
        private RaceModelSO _race;

        private void OnEnable()
        {
            _race = race;
        }

        private void OnValidate()
        {
            if (race != _race)
            {
                _race = race;
                textures.Clear();
                if (race)
                {
                    var slots = race.GetRaceBodySlots();
                    if (slots.Length != 0)
                    {
                        for (int i = 0; i < slots.Length; i++)
                        {
                            Textures newTexture = new Textures();
                            newTexture.raceSlot = slots[i];
                            textures.Add(newTexture);
                        }
                    }
                }
                // 仅在数据实际变更时标记Dirty,且加条件编译
#if UNITY_EDITOR
                EditorUtility.SetDirty(this);
#endif
            }
        }
    }

    [Serializable]
    public class Textures
    {
        public RaceSlotSO raceSlot;
        public Texture normalMap;
        public Texture albedoMap;
        public Texture metalicMap;
        public Texture ambientOcullsionMap;
        public Texture emissionMap;
    }
}
额外持久化方案(可选)

如果需要额外的备份机制,可以在类中添加右键菜单功能,将ScriptableObject内容序列化为JSON存储到本地:

#if UNITY_EDITOR
[ContextMenu("导出配置到JSON")]
public void ExportToJson()
{
    string json = EditorJsonUtility.ToJson(this, prettyPrint: true);
    string path = EditorUtility.SaveFilePanel("导出配置", Application.dataPath, name + ".json", "json");
    if (!string.IsNullOrEmpty(path))
    {
        System.IO.File.WriteAllText(path, json);
        AssetDatabase.Refresh();
    }
}

[ContextMenu("从JSON导入配置")]
public void ImportFromJson()
{
    string path = EditorUtility.OpenFilePanel("导入配置", Application.dataPath, "json");
    if (!string.IsNullOrEmpty(path))
    {
        string json = System.IO.File.ReadAllText(path);
        EditorJsonUtility.FromJsonOverwrite(json, this);
        EditorUtility.SetDirty(this);
    }
}
#endif

修改完成后,每次编辑完ScriptableObject内容按Ctrl+S保存项目即可,重启Unity不会再丢失修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 01:09:04