SerializedProperty.FindPropertyRelative returns null with ScriptableObjects

I’m trying to write some editor scripts, but I keep running into some really weird behavior for FindPropertyRelative.

Let’s say I have these classes:

[Serializable]
public class SimpleClass : ScriptableObject
{
    [SerializeField]
    public int myField;
}

public class SimpleClassBehavior : MonoBehaviour
{
    [SerializeField]
    private SimpleClass simple;
}

[CustomEditor(typeof(SimpleClass))]
public class SimpleClassEditor : Editor
{
    public override void OnInspectorGUI()
    {
        var myField = serializedObject.FindProperty("myField");
        // This works fine
    }
}

[CustomEditor(typeof(SimpleClassBehavior))]
public class SimpleClassBehaviorEditor : Editor
{
    SerializedProperty simpleClass = null;
    SerializedProperty myField = null;

    void OnEnable()
    {
        simpleClass = serializedObject.FindProperty("simple");
        // This works fine

        myField = simpleClass.FindPropertyRelative("myField");
        // This does NOT work. This returns null 100% of the time.

        int myFieldInt = (simpleClass.objectReferenceValue as SimpleClass).myField;
        // This works perfectly, but I shouldn't have to do this.
    }
}

I’m having an issue where calling FindPropertyRelative returns null. I know the object I’m looking for exists, because I can get it in other ways.

Any news on this issue?

Having similar problems (thought property is not always null, getting null sporadically).

Thanks!

EDIT: Just installed the latest Unity version (4.2.1f4) and it works. It was broken in 4.2.1.

Try this one. It works for me.

   SerializedObject newserobj = new SerializedObject(serializedObject.FindProperty("scriptable").objectReferenceValue );
     EditorGUILayout.PropertyField(newserobj.FindProperty("value"));   
     newserobj.ApplyModifiedProperties();

http://answers.unity.com/answers/1188103/view.html

This has been annoying me for too long, so I wrote up a “fix” version of the FindPropertyRelative function using Neovivacity’s solution. It has one important difference from the usual Unity-version of this function. It takes, as the last parameter a reference to a SerializedObject. You can start out with this value as null, and the function will create one (if needed). The important thing to remember is to apply changes to this SerializedObject, at the end of your Drawing functions.

If you spot any flaws or holes in the following, please let me know.

Sample usage:

public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{

SerializedObject so = null;
SerializedProperty spSegements = property.FindPropertyRelativeFix("numberOfRadialSegments", ref so);
SerializedProperty spgearInnerRadiusFraction = property.FindPropertyRelativeFix("gearInnerRadiusFraction", ref so);

position.height = EditorGUIUtility.singleLineHeight;

EditorGUI.PropertyField(position, spSegements);
position.y += EditorGUI.GetPropertyHeight(spSegements);

EditorGUI.PropertyField(position, spgearInnerRadiusFraction);
position.y += EditorGUI.GetPropertyHeight(spgearInnerRadiusFraction);

if (so != null)
    so.ApplyModifiedProperties();
}

The actual fix function, and a function it uses:

 static public SerializedProperty FindPropertyRelativeFix(this SerializedProperty sp, string name, ref SerializedObject objectToApplyChanges)
        {
            SerializedProperty result;
            if (typeof(ScriptableObject).IsAssignableFrom(sp.GetFieldType()) )
            {
                if (sp.objectReferenceValue == null) return null;
                if (objectToApplyChanges == null)
                    objectToApplyChanges = new SerializedObject(sp.objectReferenceValue);
                result = objectToApplyChanges.FindProperty(name);
            }
            else
            {
                objectToApplyChanges = null;
                result = sp.FindPropertyRelative(name);
            }
            return result;
        }


 static public System.Type GetFieldType(this SerializedProperty property)
        {
            if (property.serializedObject.targetObject == null) return null;
            System.Type parentType = property.serializedObject.targetObject.GetType();
            System.Reflection.FieldInfo fi = parentType.GetFieldViaPath(property.propertyPath);
            string path = property.propertyPath;
            if (fi == null)
                return null;
           
            return fi.FieldType;
        }

So MyClass references MyScriptable that contains MyProperty. We want to access MyProperty from MyClassEditor.

MyClassEditor:

SerializedProperty myScriptable = serializedObject.FindProperty("myScriptable");
SerializedProperty myProperty = myScriptable.FindPropertyRelative("MyProperty"); // This is null 

This is my solution:

MyScriptableEditor:

SerializedProperty MyProperty = myScriptable.FindProperty("MyProperty");

MyClassEditor:

MyScriptableEditor myScriptableEditor = CreateEditor(MyScriptable) as MyScriptableEditor;
SerializedProperty myProperty = MyScriptableEditor.myProperty;
myProperty.serializedObject.ApplyModifiedProperties();

Warning: If you put CreateEditor in OnInspectorGUI, will cause a memory leak.