Unity自定义EditorWindow切换焦点时列表内容被清除问题求助
问题原因
字段内容切换焦点后丢失的核心原因是每次OnGUI调用时都重新创建SerializedObject实例,导致输入的修改还未同步到窗口的序列化数据中,就被新实例读取的原始数据覆盖。另外,EditorUtility.SetDirty在这里属于多余操作,甚至可能干扰序列化流程。
解决方案
修改编辑器窗口代码,缓存SerializedObject实例,并在OnGUI中正确执行数据同步流程:
- 声明类级别的
SerializedObject变量缓存实例 - 在
OnEnable方法中初始化该实例 - 在
OnGUI开头调用so.Update()读取最新窗口数据 - 移除不必要的
EditorUtility.SetDirty调用
修改后的完整代码:
#if UNITY_EDITOR using System; using UnityEditor; using UnityEngine; using System.Collections.Generic; using System.Linq; namespace Tiles { public class CustomEditorWindow : EditorWindow { [SerializeField] private List<CustomAdditionalData> payloadList = new List<CustomAdditionalData>(); // 缓存SerializedObject实例 private SerializedObject so; [MenuItem("Tools/Custom Window")] public static void ShowWindow() { var desiredDockWindow = Type.GetType("UnityEditor.InspectorWindow,UnityEditor.dll"); GetWindow<CustomEditorWindow>("Custom Window", true, desiredDockWindow).Show(); } private void OnEnable() { // 初始化SerializedObject so = new SerializedObject(this); } private void OnGUI() { // 读取最新的窗口数据到SerializedObject so.Update(); var payloadListProperty = so.FindProperty(nameof(payloadList)); EditorGUILayout.PropertyField(payloadListProperty, true); // 将修改同步回窗口的序列化数据 so.ApplyModifiedProperties(); EditorGUILayout.Space(); if (GUILayout.Button("Simulate")) { SimulateButton(); } } private void SimulateButton() { var payloadDict = payloadList.ToDictionary(payloadAdditionalData => payloadAdditionalData.PayloadKey, payloadAdditionalData => payloadAdditionalData.PayloadValue); //Do something with the payloadDict } } [Serializable] public class CustomAdditionalData { public string PayloadKey; public string PayloadValue; } } #endif
额外说明
- 将
CustomAdditionalData类移入命名空间内,避免序列化时出现类型不可访问的潜在问题 SerializedObject.Update()负责从窗口实例读取最新数据,ApplyModifiedProperties()负责将修改写回窗口实例,两者配合确保数据正确同步- 新版Unity中
EditorUtility.SetDirty已标记为过时,针对ScriptableObject(包括EditorWindow),使用SerializedObject的同步方法或Undo.RecordObject处理修改即可
内容的提问来源于stack exchange,提问作者Lotan
相关产品推荐
相关产品推荐

