通常情况下:不要直接访问和更改您的MonoBehaviour实例的值!
正如您所指出的,您将不得不处理各种标记脏和保存自己的任务。当您在编辑器中重新打开场景时,您会遇到一些未正确标记为脏的问题,因此未与场景一起保存。
始终要通过处理所有标记脏、保存以及撤销/重做等操作的
SerializedProperty
来完成,这样会更好。
[CustomEditor(typeof(test))]
public class testEditor : Editor
{
private SerializedProperty Data;
public void OnEnable()
{
Data = serializedObject.FindProperty(nameof(test.Data));
}
public override void OnInspectorGUI()
{
DrawDefaultInspector();
serializedObject.Update();
if (GUILayout.Button("Add"))
{
Data.arraySize++;
}
if (GUILayout.Button("Clear"))
{
Data.arraySize = 0;
}
serializedObject.ApplyModifiedProperties();
}
}
现在,所有的标记脏数据、正确保存场景、自动撤销/重做等操作都已经处理好了,你不再需要再去关心这些了。
然后是一个小的专业提示:使用
ReorderableList
!它看起来有点棘手设置,但非常强大:正如其名称所示,它允许您在检查器中通过拖放来轻松重新排序元素,并且还允许删除列表中间的项目,这是普通列表抽屉不可能做到的。这完全替代了您的
Add
和
Clear
按钮:
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(test))]
public class testEditor : Editor
{
private SerializedProperty Data;
private ReorderableList dataList;
public void OnEnable()
{
Data = serializedObject.FindProperty(nameof(test.Data));
dataList = new ReorderableList(serializedObject, Data, true, true, true, true)
{
drawHeaderCallback = rect => EditorGUI.LabelField(rect, Data.displayName),
elementHeightCallback = index =>
{
var element = Data.GetArrayElementAtIndex(index);
var elementList = element.FindPropertyRelative(nameof(data.list));
return EditorGUIUtility.singleLineHeight * (elementList.isExpanded ? elementList.arraySize + 4 : 3);
},
drawElementCallback = (rect, index, isFocused, isActive) =>
{
var element = Data.GetArrayElementAtIndex(index);
EditorGUI.LabelField(new Rect(rect.x,rect.y,rect.width,EditorGUIUtility.singleLineHeight), element.displayName);
rect.y += EditorGUIUtility.singleLineHeight;
var elementList = element.FindPropertyRelative(nameof(data.list));
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight * (elementList.isExpanded ? elementList.arraySize + 1 : 1)), elementList, true);
}
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();
dataList.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
}
![enter image description here](https://istack.dev59.com/H3RbY.gif)
注意:如果尚未如此,
testEditor
部分应该
- either be placed in a different script in a folder called
Editor
or you should wrap anything related to the UnityEditor
namespace within pre-processors like
#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
#endif
...
#if UNITY_EDITOR
[CustomEditor(typeof(test))]
public class testEditor : Editor
{
...
}
#endif
否则,在构建应用程序时会出现错误,因为
UnityEditor
命名空间在构建中被剥离,仅存在于Unity编辑器本身中。
DontDestroyOnLoad(this.gameObject);
- Ghost The Punisher