- Home /
Property Drawer SerializedProperty is null
I have a class called OverlayObject, with an enum and a few sub-classes. I would like to make it so that the enum's value changes what class is being displayed. This works with a simple custom editor script, until I realized I needed an array of OverlayObjects. After doing a bit of research, I have determined using a custom Property Drawer is the best (or rather only) solution. I created the custom drawer, but it keeps telling me the SerializedProperty is null. Here is the code in hopefully the most concise form possible:
//Scripts/RandomGeneration.cs
[CreateAssetMenu(fileName = "Random Generation", menuName = "Algorithms/RandomGeneration")]
public class RandomGeneration : AlgorithmBase {
public OverlayObject[] overlayObjects;
//Body
}
[Serializable]
public class OverlayObject {
public TilemapStructure tilemapTypeOverlay;
public NoiseValuesGroundOverlay[] groundTileTypesOverlay;
public NoiseValuesResourceOverlay[] resourceTileTypesOverlay;
public NoiseValuesObjectOverlay[] objectTileTypesOverlay;
}
In the first file, I create the OverlayObject and declare it in RandomGeneration.
//Editor/RandomGenerationEditor
[CustomEditor(typeof(RandomGeneration))]
public class RandomGenerationEditor : Editor {
public override void OnInspectorGUI() {
var serializedObject = new SerializedObject(target);
serializedObject.Update();
//Logic to determine if the field should be shown based on a boolean
EditorGUILayout.PropertyField(serializedObject.FindProperty("overlayObjects"), true);
serializedObject.ApplyModifiedProperties();
}
}
In this custom editor script, I do some simple logic to decide if the field should be displayed. Everything works to this point.
//Editor/OverlayObjectDrawer
[CustomPropertyDrawer(typeof(OverlayObject))]
public class OverlayObjectDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
Rect contentPosition = EditorGUI.PrefixLabel(position, label);
EditorGUI.indentLevel = 0;
EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("position"), GUIContent.none);
}
}
This is where the code breaks down. This is the entire custom drawer file, so I know it isn't something else in the file. Everything displays correctly when the array size is set to 0, but when set to 1 or more I get an error. My thought was perhaps that the array was instantiated with a length of 0, but that doesn't make a ton of sense. I've gotten more familiar with editor scripting lately, but this is my first time using a property drawer, so I would really appreciate any help!
Answer by Bunny83 · Oct 31, 2020 at 01:44 AM
Well, your code is confusing. Your OverlayObjectDrawer is supposed to draw an "OverlayObject" since that's the type you attached this drawer to. Your OverlayObject class has 4 fields tilemapTypeOverlay
, groundTileTypesOverlay
, resourceTileTypesOverlay
and objectTileTypesOverlay
. Though your drawer searches for a field called "position" which of course doesn't exist in your class. So of course the call to FindPropertyRelative will return null since that field does not exist: property.FindPropertyRelative("position")
.
Instead you want to use one of the existing fields. For example: var tilemapTypeOverlayProp = property.FindPropertyRelative("tilemapTypeOverlay"); EditorGUI.PropertyField(contentPosition, tilemapTypeOverlayProp, GUIContent.none); switch (tilemapTypeOverlayProp.enumValueIndex) { .... }
Keep in mind when you use the PropertyField overload that takes a GUIContent label and you pass "none" as label you can't really know what the content of this property belongs to. If you just want to draw the property as usual, use the other overload without a label.
When you implement a property drawer for a property, you are responsible for displaying the whole property and it's content. In my code snippets I implemented a switch based on the enum value index of the "tilemapTypeOverlay" field.
Thank you - I actually just found the error myself too. I was following a tutorial and didn't realize that "position"
was the name of the variable, I thought it was a reserved word.
Answer by Eagle-Bound · Oct 31, 2020 at 02:40 AM
So... turns out I'm just dumb. Posting what went wrong in case someone else stumbles across this. In the custom drawer, I say property.FindPropertyRelative("position")
following this tutorial, but I didn't realize "position"
was the variable name, and I have no variable named position
so that's why it was throwing an error. In my case, I just had to change it to property.FindPropertyRelative("tilemapTypeOverlay")
.
Just realized that's what @Bunny83 said - they are right