UnityEditor List<ExposedReference>新增条目自动复制上一项值问题
ExposedReference列表新增条目复制上一项值的解决方案
问题根因
Unity Editor下所有序列化列表的默认新增逻辑,都会直接拷贝列表最后一个元素的序列化内存数据生成新条目,不会主动调用类型的构造函数生成全新实例。ExposedReference<T>作为Unity内置的可序列化类型,没有自带默认新增重置逻辑,就会出现新条目完全复用上一项exposedName和defaultValue的问题。
可落地方案
方案1:IMGUI ReorderableList 自定义新增回调(最常用)
之前写的回调没生效,核心是调用了默认的AddNewItem()方法触发了内置拷贝逻辑,替换成手动插入数组元素+定向重置新条目属性即可,全程不会改动已有条目的值:
// 初始化可排序列表时绑定自定义新增逻辑 ReorderableList exposedRefList = new ReorderableList(serializedObject, serializedObject.FindProperty("yourExposedReferenceListField"), true, true, true, true); exposedRefList.onAddCallback = list => { SerializedProperty listProp = list.serializedProperty; // 手动在列表末尾插入空元素,跳过默认的拷贝最后一项逻辑 listProp.InsertArrayElementAtIndex(listProp.arraySize); // 仅获取刚新增的最后一个元素的序列化属性 SerializedProperty newItem = listProp.GetArrayElementAtIndex(listProp.arraySize - 1); // 重置ExposedReference的两个核心字段 newItem.FindPropertyRelative("exposedName").FindPropertyRelative("stringValue").stringValue = string.Empty; newItem.FindPropertyRelative("defaultValue").objectReferenceValue = null; // 应用修改 listProp.serializedObject.ApplyModifiedProperties(); };
方案2:UIToolk ListView 拦截新增事件
如果用UIToolkit开发Inspector,拦截itemsAdded事件定向重置新条目即可:
listView.itemsAdded += addedIndices => { SerializedObject so = listView.viewController.serializedObject; SerializedProperty listProp = so.FindProperty("yourExposedReferenceListField"); foreach (int newIndex in addedIndices) { SerializedProperty newItem = listProp.GetArrayElementAtIndex(newIndex); newItem.FindPropertyRelative("exposedName").FindPropertyRelative("stringValue").stringValue = string.Empty; newItem.FindPropertyRelative("defaultValue").objectReferenceValue = null; } so.ApplyModifiedProperties(); };
避坑说明
- 不要尝试给
ExposedReference写扩展构造函数规避,Unity序列化生成新元素时不会调用自定义构造函数,只会走内存拷贝,构造逻辑不生效。 - 重置操作只针对刚新增的索引对应的序列化属性,不要遍历全列表重置,否则会覆盖已有条目的赋值。
- 如果用Odin Inspector等第三方插件绘制列表,直接给列表特性传入自定义新增方法,逻辑和上述一致即可,禁用默认的拷贝新增行为。
内容的提问来源于stack exchange,提问作者rever
相关产品推荐
相关产品推荐

