Unity编辑器脚本修改TranslationData ScriptableObject无法永久保存求助
解决ScriptableObject在自定义Editor中修改后无法永久保存的问题
直接修改ScriptableObject实例字段并调用EditorUtility.SetDirty的方式,在新版Unity中可能无法被序列化系统正确追踪,导致重启或构建后改动丢失。正确的做法是通过SerializedObject/SerializedProperty体系来操作,让Unity完整记录所有序列化数据的变更。
核心思路
- 不要直接操作
TranslationData的实例字段,而是通过SerializedObject包装它,用SerializedProperty访问和修改内部数据。 - 所有修改操作完成后,必须调用
ApplyModifiedProperties()让改动被序列化系统认可。 - 最后通过
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
相关产品推荐
相关产品推荐

