SerializedObject.FindProperty returning null

Firstly I am missing my inheritFrom field when using the normal Inspector (not anymore when I inherit from UnityEngine.Object, then there’s just 1 field):

[DataContract]
[System.Serializable]
public class BotPersonality : UnityEngine.Object
{

[DataMember]
[JsonProperty]
[SerializeField]
private BotPersonality _inheritFrom;

[DataMember]
[JsonProperty]
[SerializeField]
private string[] _possibleNames = {"test1", "test2"};

Inspector normal

I want to write a custom inspector for inheriting / copying fields from another object with _inheritFrom.

However I am getting NullReferenceExceptions ( SerializedObject.FindProperty returns null) for all my fields.
nullRefException

it says it can’t find the skill property, but it is clearly defined and it works in the first image.:

[DataMember]
[SerializeField]
public int skill = 1;

The skill variable is serializable.

Below is my PropertyDrawer class

    [CustomPropertyDrawer(typeof(BotPersonality))]
    public class BotPersonalityDrawer : PropertyDrawer
    {
        private readonly Type _type = typeof(BotPersonality);

public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
    BotPersonality botPersonality =
        Utils.GetActualObjectForSerializedProperty<BotPersonality>(this.fieldInfo, property);    
    this.ShowPersonality(botPersonality, property);
}

    private void ShowPersonality(BotPersonality bot, SerializedProperty property)
    {
        int prevIndentLevel = EditorGUI.indentLevel;
         foreach (FieldInfo fieldType in this._type.GetFields()
                        .Where(x => x.IsDefined(typeof(DataMemberAttribute), false)))
        {
        ...
        var serializedProperty = property.serializedObject.FindProperty(fieldType.Name);
            EditorGUILayout.PropertyField(serializedProperty);
        }
}
}

The code for GetActualObjectForSerializedProperty can be found here: http://sketchyventures.com/2015/08/07/unity-tip-getting-the-actual-object-from-a-custom-property-drawer/ (I changed it so it works with lists too ), but this an object that is not null.

Help would be much appreciated. I can’t see what I’m doing wrong.

EDIT: To clarify, I’m not looking for help with the inheritance / copy an object.

EDIT2: I’ve created it as small as I can and it still gives the same NullRef Exception:

[DataContract]
[System.Serializable]
public class BotPersonalitySmall : MonoBehaviour
{
    [DataMember]
    [SerializeField]
    public int skill = 1;
    [DataMember]
    [SerializeField]
    private BotPersonalitySmall _inheritFrom;
    [DataMember]
    [Overridable]
    public BotPersonality.WaypointSteeringInfo waypointSteering;
}

The class I’m trying to serialize

The PropertyDrawer:

[CustomPropertyDrawer(typeof(BotPersonalitySmall))]
public class BotPersonalitySmallDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // Using BeginProperty / EndProperty on the parent property means that
        // prefab override logic works on the entire property.
        EditorGUI.BeginProperty(position, label, property);
        var serializedProperty = property.serializedObject.FindProperty("skill");
        EditorGUILayout.PropertyField(serializedProperty);
        EditorGUI.EndProperty();
    }
}

It still can’t find the property skill. I’ve changed the inheritance on BotPersonality to UnityEngine.Object or keep it empty, but that didn’t help.

This is quite confusing. You showed random bits of your code and your inspector. What does “BotPersonality” look like? Is it a serializable class / struct? What Tyoe does “this._type” refer to?

This line looks suspicious:

var serializedProperty = property.serializedObject.FindProperty(fieldType.Name);

You may have the wrong idea in mind what a SerializedObject is. SerializedObjects are only those objects which are derived from UnityEngine.Object. Custom serializable classes are not objects from the serialization systems point of view. Custom serializable classes get simply serialized “inline” as sub fields.

The SerializedProperty class has a method called FindPropertyRelative which can search for a sub property. It’s possible to use FindProperty on the serializedObject when you use a correct property path. In your case it would be something like “_inheritFrom.skill”.

Also keep in mind that you can not use polymorphism / inheritance for custom serializable classes. You may want to have a look at the script serialization documentation

I found out how to copy using Json. So I’ll just use that instead of this (was my original plan anyway)

"idName": "test2",
"copyValuesFromId": "test",

And then I loop through all the fields

  foreach (BotPersonality bp in this.botPersonalities)
    {
    try
    if (String.IsNullOrEmpty(bp.copyValuesFromId) ||
        bp.copyValuesFromId.Equals("none", StringComparison.CurrentCultureIgnoreCase)) continue;
    BotPersonality copyFrom = this.botPersonalities.Find(x =>
        String.Equals(x.idName, bp.copyValuesFromId, StringComparison.CurrentCultureIgnoreCase));
    Assert.IsNotNull(copyFrom, "Id was not found in CopyValuesFromId " + bp.copyValuesFromId);
        foreach (FieldInfo fi in typeof(BotPersonality).GetFields(_BIND_FLAGS)
        .Where(x => x.IsDefined(typeof(DataMemberAttribute), false)))
    {
        // we only copy values that are null
        if (!ShouldCopyValue(fi, bp)) continue;
        fi.SetValue(bp, fi.GetValue(copyFrom));
    }
}

Then ShouldCopyValue checks if it set to the default values

private static bool ShouldCopyValue(FieldInfo fi, BotPersonality bp)
{
    object value = fi.GetValue(bp);
    if (value == null)
        return true;
    Type t = value.GetType();
    if (t == typeof(int))
        return (int) value == Int32.MinValue;
    if (t == typeof(float))
        return ((float) value).AboutEqualTo(Single.MinValue);
    if (t.IsPrimitive)
        throw new Exception("Type " + t + " is not supported yet for bp: " + bp.idName);
    return false;
}

Thank you anyway @bunny83 for all the explanations :slight_smile: