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

Unity编辑器脚本修改TranslationData ScriptableObject无法永久保存求助

解决ScriptableObject在自定义Editor中修改后无法永久保存的问题

直接修改ScriptableObject实例字段并调用EditorUtility.SetDirty的方式,在新版Unity中可能无法被序列化系统正确追踪,导致重启或构建后改动丢失。正确的做法是通过SerializedObject/SerializedProperty体系来操作,让Unity完整记录所有序列化数据的变更。

核心思路

  1. 不要直接操作TranslationData的实例字段,而是通过SerializedObject包装它,用SerializedProperty访问和修改内部数据。
  2. 所有修改操作完成后,必须调用ApplyModifiedProperties()让改动被序列化系统认可。
  3. 最后通过AssetDatabase完成持久化保存。

示例代码

假设你的TranslatableText有一个关联的TranslationData字段,自定义Editor中的正确实现如下:

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(TranslatableText))]
public class TranslatableTextEditor : Editor
{
    private SerializedProperty _translationDataProp;
    private string _textFieldValue = "example_key"; // 替换为你的输入字段值

    private void OnEnable()
    {
        // 获取TranslatableText上的translationData字段
        _translationDataProp = serializedObject.FindProperty("translationData");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        
        // 绘制默认Inspector(可选)
        DrawDefaultInspector();

        // 自定义修改操作示例
        if (GUILayout.Button("添加/更新翻译项"))
        {
            ModifyTranslationData();
        }

        serializedObject.ApplyModifiedProperties();
    }

    private void ModifyTranslationData()
    {
        if (_translationDataProp.objectReferenceValue == null)
        {
            Debug.LogError("请先关联TranslationData资源");
            return;
        }

        // 包装TranslationData为SerializedObject,用于追踪改动
        SerializedObject dataSO = new SerializedObject(_translationDataProp.objectReferenceValue);
        // 获取data字段的SerializedProperty(假设data是可序列化的字典/列表)
        SerializedProperty dataProp = dataSO.FindProperty("data");

        // 检查目标键是否已存在
        bool keyExists = false;
        for (int i = 0; i < dataProp.arraySize; i++)
        {
            SerializedProperty entry = dataProp.GetArrayElementAtIndex(i);
            SerializedProperty keyProp = entry.FindPropertyRelative("key");
            
            if (keyProp.stringValue == _textFieldValue)
            {
                // 更新已有键对应的Node
                SerializedProperty valueProp = entry.FindPropertyRelative("value");
                valueProp.managedReferenceValue = new TranslationData.Node();
                keyExists = true;
                break;
            }
        }

        // 如果键不存在,添加新的键值对
        if (!keyExists)
        {
            dataProp.arraySize++;
            SerializedProperty newEntry = dataProp.GetArrayElementAtIndex(dataProp.arraySize - 1);
            newEntry.FindPropertyRelative("key").stringValue = _textFieldValue;
            newEntry.FindPropertyRelative("value").managedReferenceValue = new TranslationData.Node();
        }

        // 应用TranslationData的修改,让序列化系统记录变更
        dataSO.ApplyModifiedProperties();
        // 标记资源为脏状态
        EditorUtility.SetDirty(_translationDataProp.objectReferenceValue);
        // 保存所有修改到磁盘
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }
}

关键注意事项

  • 确保序列化兼容性:TranslationData的data字段必须是Unity可序列化的类型。如果用字典,需要自定义可序列化的字典实现(比如继承ScriptableObject并使用[Serializable]标记键值对类),因为默认Dictionary<TKey, TValue>无法被Unity直接序列化。
  • 避免直接修改实例:所有涉及序列化字段的修改,都要通过SerializedProperty完成,绕开这个体系会导致Unity无法追踪变更。
  • 调用ApplyModifiedProperties:无论修改的是TranslatableText还是TranslationData的SerializedObject,都必须调用这个方法,否则改动不会被写入到实际对象中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 06:31:17