- Home /
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.
Answer by dkozar · Oct 03, 2013 at 05:23 PM
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.
I have not found a true solution. I am already using 4.2.1f4.
Hm... what I did is I don't do a property lookup (FindPropertyRelative) within the Editor.
I created a base class for the structure I'd like to display in the editor, which has it's property drawer.
So I'm doing the lookup and rendering inside of the property drawer. This is what didn't work properly with the old Unity version.
You might want to check article on property drawers by CatlikeCoding: http://catlikecoding.com/unity/tutorials/editor/custom-data/ Great articles! $$anonymous$$ight inspire you...
It works from $$anonymous$$onoBehaviour as well.
$$anonymous$$y $$anonymous$$onoBehaviour is having only a single property (no 'FindPropertyRelative' calls here):
public class Your$$anonymous$$onoBehaviour: $$anonymous$$onoBehaviour
{
public YourClassToSerialize YourClass;
}
There's an editor for it:
[CanEdit$$anonymous$$ultipleObjects]
[CustomEditor(typeof(Your$$anonymous$$onoBehaviour))]
public class Your$$anonymous$$onoBehaviourEditor : Editor {
private SerializedProperty GetYourClass()
{
return serializedObject.FindProperty("YourClass");
}
void OnGUI() {
if (GUILayout.Button(new Rect(10, 10, 100, 30), "Click me") {
SerializedProperty yourClass = GetYourClass();
yourClass.FindPropertyRelative("yourField"); // works!
}
}
}
Yeah, I actually tried using PropertyDrawers, with the same result. No matter the approach, I can only get a SerializedProperty from a SerializedObject. But I can't get a SerializedProperty from another SerializedProperty.
This thread is pretty old, but in case anyone stumbles across it looking for answers like me, I solved the issue stated by vogles:
To get a SerializedProperty of a SerializedProperty, create a new SerializedObject from the the first SerializedProperty.objectReferenceValue. Then use FindProperty from that.
Example:
SerializedProperty prop;//Your existing property
SerializedObject propObj = new SerializedObject(prop.objectReferenceValue);
SerializedProperty childProp = propObj.FindProperty("name");
Answer by Hanh · May 24, 2018 at 09:51 AM
Try this one. It works for me.
SerializedObject newserobj = new SerializedObject(serializedObject.FindProperty("scriptable").objectReferenceValue );
EditorGUILayout.PropertyField(newserobj.FindProperty("value"));
newserobj.ApplyModifiedProperties();
Answer by Glurth · Apr 19, 2018 at 04:57 PM
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;
}
@Bunny83 Just wanted to see if the expert had any criticism/suggestions regarding this answer/solution- I feel like something is "off" serialization-wise, but I'm not sure what (works fine, for my limited tests).
Answer by luislodosm · Jan 21, 2018 at 08:37 PM
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.
Your answer
![](https://koobas.hobune.stream/wayback/20220613114759im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Select custom object from a list via PopUp in custom editor for ScriptableObject 0 Answers
Display Custom Inspectors for each class in a List<> 1 Answer
Null SerializedProperty SerializedObject upon Removal from list 1 Answer
How to get "name" member of a ScriptableObject, as a SerializedProperty 2 Answers
How do I associate my custom object for the serializedProperty objectReferenceValue 1 Answer