this.thingsProperty is not the List variable. Its returning a SerializedProperty object. You will have to get the contents of your list from the SerializedProperty object. Generally, SerializedProperty will store your data in one of its many data fields based on the type of the data. For example, bool data values are stored in the [SerializedProperty.boolValue][1] field. There are other types for ints, floats, etc. References to objects are stored in [.objectReferenceValue][2] So the basic way of working with SerializedProperties is to get the property, then get the value from the appropriate field depending on the data type you’re expecting.
SerializedProperty stores arrays in a special way (and it just treats a list as an array). It doesn’t just store the array as an object which you can easily grab and work with. Instead, it stores a bunch of data for the array in various fields. Basically, you test if the field is an array with isArray, then step through the fields with SerializedProperty.Next(true) to get to the parts of the array like the length, and finally the data fields. Once you get the data, you still have to know its type and access it through SerializedProperty.boolValue or whatever type it is.
Here is an example of one to get the data from an array/list in a SerialzedObject:
[CustomEditor(typeof(MyTestType))]
public class SOListtest : Editor {
private SerializedProperty thingsProperty;
private void OnEnable() {
this.thingsProperty = this.serializedObject.FindProperty("_things");
}
public override void OnInspectorGUI() {
this.serializedObject.Update();
SerializedProperty sp = thingsProperty.Copy(); // copy so we don't iterate the original
if(sp.isArray) {
int arrayLength = 0;
sp.Next(true); // skip generic field
sp.Next(true); // advance to array size field
// Get the array size
arrayLength = sp.intValue;
sp.Next(true); // advance to first array index
// Write values to list
List<int> values = new List<int>(arrayLength);
int lastIndex = arrayLength - 1;
for(int i = 0; i < arrayLength; i++) {
values.Add(sp.intValue); // copy the value to the list
if(i < lastIndex) sp.Next(false); // advance without drilling into children
}
// iterate over the list displaying the contents
for(int i = 0; i < values.Count; i++) {
EditorGUILayout.LabelField(i + " = " + values*);*
}
}
this.DrawDefaultInspector(); // show the default inspector so we can set some values
}
}
And here is the MonoBehaviour that the inspector inspects:
public class MyTestType : MonoBehaviour {
public List things {
get {
return _things;
}
set {
_things = value;
}
}
[SerializeField]
private List _things;
}
FYI, there are also other methods you can use to access and work with arrays in SerializedProperty:
[SerializedProperty.ClearArray][3],
[SerializedProperty.DeleteArrayElementAtIndex][4],
[SerializedProperty.GetArrayElementAtIndex][5],
[SerializedProperty.InsertArrayElementAtIndex][6],
[SerializedProperty.MoveArrayElement][7]
Additionally, you can directly access the contents of an array via [SerializedObject.FindProperty][8] by passing it a string to the path using this syntax:
“fieldName.Array.data[0].fieldName”
Below are some methods I made to help with working with SerializedProperties. You can see how arrays are stored and how to iterate through all the properties to discover the structure.
public static void LogProperties(SerializedObject so, bool includeChildren = true) {
// Shows all the properties in the serialized object with name and type
// You can use this to learn the structure
so.Update();
SerializedProperty propertyLogger = so.GetIterator();
while(true) {
Debug.Log("name = " + propertyLogger.name + " type = " + propertyLogger.type);
if(!propertyLogger.Next(includeChildren)) break;
}
}
// variablePath may have a structure like this:
// “meshData.Array.data[0].vertexColors”
// So it uses FindProperty to get data from a specific field in an object array
public static void SetSerializedProperty(UnityEngine.Object obj, string variablePath, object variableValue) {
-
SerializedObject so = new SerializedObject(obj);*
-
SerializedProperty sp = so.FindProperty(variablePath);*
-
if(sp == null) {*
-
Debug.Log("Error setting serialized property! Variable path: \"" + variablePath + "\" not found in object!");*
-
return;*
-
}*
-
so.Update(); // refresh the data*
-
//SerializedPropertyType type = sp.propertyType; // get the property type*
-
System.Type valueType = variableValue.GetType(); // get the type of the incoming value*
-
if(sp.isArray && valueType != typeof(string)) { // serialized property is an array, except string which is also an array*
-
// assume the incoming value is also an array*
-
if(!WriteSerializedArray(sp, variableValue)) return; // write the array*
-
} else { // not an array*
-
if(!WriteSerialzedProperty(sp, variableValue)) return; // write the value to the property*
-
}*
-
so.ApplyModifiedProperties(); // apply the changes*
-
}*
-
private static bool WriteSerialzedProperty(SerializedProperty sp, object variableValue) {*
-
// Type the property and fill with new value*
-
SerializedPropertyType type = sp.propertyType; // get the property type*
-
if(type == SerializedPropertyType.Integer) {*
-
int it = (int)variableValue;*
-
if(sp.intValue != it) {*
-
sp.intValue = it;*
-
}*
-
} else if(type == SerializedPropertyType.Boolean) {*
-
bool b = (bool)variableValue;*
-
if(sp.boolValue != b) {*
-
sp.boolValue = b;*
-
}*
-
} else if(type == SerializedPropertyType.Float) {*
-
float f = (float)variableValue;*
-
if(sp.floatValue != f) {*
-
sp.floatValue = f;*
-
}*
-
} else if(type == SerializedPropertyType.String) {*
-
string s = (string)variableValue;*
-
if(sp.stringValue != s) {*
-
sp.stringValue = s;*
-
}*
-
} else if(type == SerializedPropertyType.Color) {*
-
Color c = (Color)variableValue;*
-
if(sp.colorValue != c) {*
-
sp.colorValue = c;*
-
}*
-
} else if(type == SerializedPropertyType.ObjectReference) {*
-
Object o = (Object)variableValue;*
-
if(sp.objectReferenceValue != o) {*
-
sp.objectReferenceValue = o;*
-
}*
-
} else if(type == SerializedPropertyType.LayerMask) {*
-
int lm = (int)variableValue;*
-
if(sp.intValue != lm) {*
-
sp.intValue = lm;*
-
}*
-
} else if(type == SerializedPropertyType.Enum) {*
-
int en = (int)variableValue;*
-
if(sp.enumValueIndex != en) {*
-
sp.enumValueIndex = en;*
-
}*
-
} else if(type == SerializedPropertyType.Vector2) {*
-
Vector2 v2 = (Vector2)variableValue;*
-
if(sp.vector2Value != v2) {*
-
sp.vector2Value = v2;*
-
}*
-
} else if(type == SerializedPropertyType.Vector3) {*
-
Vector3 v3 = (Vector3)variableValue;*
-
if(sp.vector3Value != v3) {*
-
sp.vector3Value = v3;*
-
}*
-
} else if(type == SerializedPropertyType.Rect) {*
-
Rect r = (Rect)variableValue;*
-
if(sp.rectValue != r) {*
-
sp.rectValue = r;*
-
}*
-
} else if(type == SerializedPropertyType.ArraySize) {*
-
int aSize = (int)variableValue;*
-
if(sp.intValue != aSize) {*
-
sp.intValue = aSize;*
-
}*
-
} else if(type == SerializedPropertyType.Character) {*
-
int ch = (int)variableValue;*
-
if(sp.intValue != ch) {*
-
sp.intValue = ch;*
-
}*
-
} else if(type == SerializedPropertyType.AnimationCurve) {*
-
AnimationCurve ac = (AnimationCurve)variableValue;*
-
if(sp.animationCurveValue != ac) {*
-
sp.animationCurveValue = ac;*
-
}*
-
} else if(type == SerializedPropertyType.Bounds) {*
-
Bounds bounds = (Bounds)variableValue;*
-
if(sp.boundsValue != bounds) {*
-
sp.boundsValue = bounds;*
-
}*
-
} else {*
-
Debug.Log("Unsupported SerializedPropertyType \"" + type.ToString() + " encoutered!");*
-
return false;*
-
}*
-
return true;*
-
}*
-
private static bool WriteSerializedArray(SerializedProperty sp, object arrayObject) {*
-
System.Array[] array = (System.Array[])arrayObject; // cast to array*
-
sp.Next(true); // skip generic field*
-
sp.Next(true); // advance to array size field*
-
// Set the array size*
-
if(!WriteSerialzedProperty(sp, array.Length)) return false;*
-
sp.Next(true); // advance to first array index*
-
// Write values to array*
-
int lastIndex = array.Length - 1;*
-
for(int i = 0; i < array.Length; i++) {*
_ if(!WriteSerialzedProperty(sp, array*)) return false; // write the value to the property*_
* if(i < lastIndex) sp.Next(false); // advance without drilling into children }*
* return true;*
* }*
// A way to see everything a SerializedProperty object contains in case you don’t
// know what type is stored.
public static void LogAllValues(SerializedProperty serializedProperty) {
Debug.Log("PROPERTY: name = " + serializedProperty.name + " type = " + serializedProperty.type);
Debug.Log("animationCurveValue = " + serializedProperty.animationCurveValue);
Debug.Log("arraySize = " + serializedProperty.arraySize);
Debug.Log("boolValue = " + serializedProperty.boolValue);
Debug.Log("boundsValue = " + serializedProperty.boundsValue);
Debug.Log("colorValue = " + serializedProperty.colorValue);
Debug.Log("depth = " + serializedProperty.depth);
Debug.Log("editable = " + serializedProperty.editable);
Debug.Log("enumNames = " + serializedProperty.enumNames);
Debug.Log("enumValueIndex = " + serializedProperty.enumValueIndex);
Debug.Log("floatValue = " + serializedProperty.floatValue);
Debug.Log("hasChildren = " + serializedProperty.hasChildren);
Debug.Log("hasMultipleDifferentValues = " + serializedProperty.hasMultipleDifferentValues);
Debug.Log("hasVisibleChildren = " + serializedProperty.hasVisibleChildren);
Debug.Log("intValue = " + serializedProperty.intValue);
Debug.Log("isAnimated = " + serializedProperty.isAnimated);
Debug.Log("isArray = " + serializedProperty.isArray);
Debug.Log("isExpanded = " + serializedProperty.isExpanded);
Debug.Log("isInstantiatedPrefab = " + serializedProperty.isInstantiatedPrefab);
Debug.Log("name = " + serializedProperty.name);
Debug.Log("objectReferenceInstanceIDValue = " + serializedProperty.objectReferenceInstanceIDValue);
Debug.Log("objectReferenceValue = " + serializedProperty.objectReferenceValue);
Debug.Log("prefabOverride = " + serializedProperty.prefabOverride);
Debug.Log("propertyPath = " + serializedProperty.propertyPath);
Debug.Log("propertyType = " + serializedProperty.propertyType);
Debug.Log("quaternionValue = " + serializedProperty.quaternionValue);
Debug.Log("rectValue = " + serializedProperty.rectValue);
Debug.Log("serializedObject = " + serializedProperty.serializedObject);
Debug.Log("stringValue = " + serializedProperty.stringValue);
Debug.Log("tooltip = " + serializedProperty.tooltip);
Debug.Log("type = " + serializedProperty.type);
Debug.Log("vector2Value = " + serializedProperty.vector2Value);
Debug.Log("vector3Value = " + serializedProperty.vector3Value);
}
_[1]: https://docs.unity3d.com/Documentation/ScriptReference/SerializedProperty-boolValue.html*_
_[2]: https://docs.unity3d.com/Documentation/ScriptReference/SerializedProperty-objectReferenceValue.html*_
_[3]: http://docs.unity3d.com/Documentation/ScriptReference/SerializedProperty.ClearArray.html*_
_[4]: http://docs.unity3d.com/Documentation/ScriptReference/SerializedProperty.DeleteArrayElementAtIndex.html*_
_[5]: http://docs.unity3d.com/Documentation/ScriptReference/SerializedProperty.GetArrayElementAtIndex.html*_
_[6]: http://docs.unity3d.com/Documentation/ScriptReference/SerializedProperty.InsertArrayElementAtIndex.html*_
_[7]: http://docs.unity3d.com/Documentation/ScriptReference/SerializedProperty.MoveArrayElement.html*_
_[8]: http://docs.unity3d.com/Documentation/ScriptReference/SerializedObject.FindProperty.html*_