因为ScriptableObject 的默认PropertyField 只是您得到的:UnityEngine.Object 引用字段,例如用于游戏对象和组件以及其他资产;)
当然,您可以实现您想要实现的目标,但这有点复杂,不太适合维护,我不建议这样做。
我不知道你的ScriptableObject 所以这里举个例子
public class ExampleSO : ScriptableObject
{
public int SomeInt;
[SerializeField] private string _someString;
}
还有你的MonoBehaviour,例如
public class Example : MonoBehaviour
{
public List<ExampleSO> _SOList;
}
那么编辑器可能看起来像例如
using UnityEditor;
using UnityEngine;
// This is the namespace for the ReorderableList
using UnityEditorInternal;
[CustomEditor(typeof(Example))]
public class ExampleEditor : Editor
{
SerializedProperty _SOList;
Example _example;
MonoScript _script;
ReorderableList _list;
private void OnEnable()
{
// Link up the serializedProperty
_SOList = serializedObject.FindProperty("_SOList");
// get the casted target instance (only needed for drawing the script field)
_example = (Example) target;
// get the according script instance (only needed for drawing the script field)
_script = MonoScript.FromMonoBehaviour(_example);
// Set up the ReorderableList
_list = new ReorderableList(serializedObject, _SOList, true, true, true, true)
{
// What shall be displayed as header for the list?
drawHeaderCallback = (Rect rect) => EditorGUI.LabelField(rect, _SOList.displayName),
// How is each element displayed?
drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
{
// Get the element in the list (SerializedProperty)
var element = _SOList.GetArrayElementAtIndex(index);
// and draw the default object reference field
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element, new GUIContent("Reference"));
// Check if an asset is referenced - if not we are done here
if (!element.objectReferenceValue) return;
// Otherwise get the SerializedObject for this asset
var elementSerializedObject = new SerializedObject(element.objectReferenceValue);
// and all the properties (SerializedProperty) of it you want to display
var someInt = elementSerializedObject.FindProperty("SomeInt");
var someString = elementSerializedObject.FindProperty("_someString");
// Similar to the OnInspectorGUI first load the current values into this serializedobject
elementSerializedObject.Update();
{
// Adding some indentation just to show that the following fields are actually belonging to the referenced asset
EditorGUI.indentLevel++;
{
rect = EditorGUI.IndentedRect(rect);
// shift down the rect by one line
rect.y += EditorGUIUtility.singleLineHeight;
// Draw the field for the Int
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), someInt);
// Shift down the rect another line
rect.y += EditorGUIUtility.singleLineHeight;
// Draw the string field
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), someString);
}
EditorGUI.indentLevel--;
}
// Write back the changed values and trigger the checks for logging dirty states and Undo/Redo
elementSerializedObject.ApplyModifiedProperties();
},
// How much vertical space should be reserved for each element?
elementHeightCallback = (int index) =>
{
// Get the elements serialized property
var element = _SOList.GetArrayElementAtIndex(index);
// by default we have only the asset reference -> single line
var lines = 1;
// if the asset is referenced adds space for the additional fields
if (element.objectReferenceValue) lines += 2; // or how many lines you'll need
return lines * EditorGUIUtility.singleLineHeight;
}
};
}
public override void OnInspectorGUI()
{
// draw th script field
DrawScriptField();
// Load the current values into the serializedObject
serializedObject.Update();
{
// let the ReorderableList do its magic
_list.DoLayoutList();
}
// Write back the changed values into the actual instance
serializedObject.ApplyModifiedProperties();
}
// Just draws the usual script field at the top of the Inspector
private void DrawScriptField()
{
EditorGUI.BeginDisabledGroup(true);
{
EditorGUILayout.ObjectField("Script", _script, typeof(Example), false);
}
EditorGUI.EndDisabledGroup();
EditorGUILayout.Space();
}
}
这会产生以下 Inspector。如您所见,我打开了MonoBehaviour 的Ispectors 和ExampleSO 的两个实例,以显示如何将这些值转移到实际实例中