Can SerializedObject.FindProperty() look more than one level deep?

If I have two classes…

public class Child : MonoBehaviour {
	public int num = 5;
}
public class Parent : MonoBehaviour {
	public Child child;
}

…and If I’m writing a custom editor for “Parent”, can I use SerializedObject.FindProperty to access it’s target Parent’s “child.num”? Or can it only access direct members of the Parent, like “Parent.child”?

Basically, what will the reflection allow? Is accessing members of the targets the limit (with some special exceptions like accessing array members), or would there be a way to access Parent.child.num through the Parent’s editor (using SerializedProperties)?

Thanks for any help. I’m trying to add multi-object editing but I haven’t found a lot of good details or examples out there.
-Orion

1 Like

You could create a second serializedObject and use that to get to the properties.

E.G

SerializedObject o = new SerializedObject (child);
o.FindProperty("num ");

^ This is what I ended up doing last night. I had an “oh, duh.” moment where I got that the SerializedObject constructor just needed an Object, or Object[ ] of any old objects. Thanks for your tip.

Still don’t know if FindProperty itself can look up members of members- perhaps someone more knowledgeable than I could clarify one way or another.

I met same problem.

I want to access and modify child’s class’s property.

Public class Hero{ public List skills;}
public class Skill{ public string name;}

public class HeroEditor : MonoBehaviour {
public Hero hero1 = new Hero();
}

[CustomEditor(typeof(HeroEditor))]
public class HeroCustomEditor : Editor {

Hi guys!

I know this post is old, but i would like to know if anyway found a solution ?

How can i access my Level property if i make a Re-orderable list with my “_adventureList” ?
And how can i make a list of level in my re-orderable list ?

public class AdventureManager : MonoBehaviour
{

    public List<Adventure> _adventureList = new List<Adventure>();

}

[CustomEditor(typeof(AdventureManager))]
public class AdventureManagerEditor : Editor
{
        private ReorderableList _list;

        private void OnEnable()
        {
            SerializedObject obj = serializedObject;
            SerializedProperty prop = serializedObject.FindProperty("_adventureList");
            _list = CreateList(obj, prop);
        }
}

public class Adventure
{
    public string _name = "Adventure Name";

    public List<Level> _levels = new List<Level>();
}

public class Level
{
    public string _name = "Level Name";
    public string _sceneName = "Level Scene Name";
}

Thanks for any help . I work on custom inspector since 3 days only, so it’s a bit confused currently ^^

1 Like

You can access nested properties like this (for the OP’s code):

SerializedProperty property = serializedObject.FindProperty("child.num");

You can access list and array elements (and the size of the collection) like this (for the code immediately above):

SerializedProperty property = serializedObject.FindProperty("_adventureList.Array.data[0]._name");
SerializedProperty sizeProperty = serializedObject.FindProperty("_adventureList.Array.size");
14 Likes

I found this interesting link about the same subject recently, but there was one problem with it when it comes to use encapsulated/subclasses as it seem hierarchy “seem broken”. Thing is serializedObject seem to always be refering to the root (mono, gameobject… whatever is used). I used the script on the blog as it seems more genric in my opnion and more flexible. I also provided the fix in comment (under CrashOverride user) to be able to use it on intermediate/subclasses.

Enjoy!

Here’s a basic testClass to use. See if it behave as you expect. Require to use the script for ConditionalHideAttribute and ConditionalHidePropertyDrawer to work (in the link above).

public class PotatoScriptTest : MonoBehaviour
{
    public bool enable;
    [ConditionalHideAttribute("enable", true)]
    public string description = "desc";

    [System.Serializable]
    public class rigTest
    {
        public bool enable;

        [ConditionalHideAttribute("enable")]
        public string name = "Test";
        [ConditionalHideAttribute("enable", true)]
        public float speed = 2.0f;
    };

    public rigTest blabla;

    public rigTest[] blablaArray = new rigTest[5];

    public List<rigTest> testBlabla = new List<rigTest>();
}

Hello,
Maybe I am necroing this but I think SerializedProperty.FindPropertyRelative already existed when this post came out, so I’m leading you there → Unity - Scripting API: SerializedProperty.FindPropertyRelative

For example :

// In the MonoBehaviour script
public Test myTest;

public struct Test
{
    public int a;
}

// In the Editor script

serializedObject.FindProperty("myTest").FindPropertyRelative("a").intValue = ...
1 Like

the solution is here:

.
     
  private SerializedProperty FindSerializableProperty(string fieldName, SerializedProperty property)
        {
            string propertyPath = property.propertyPath;
            int idx = propertyPath.LastIndexOf('.');
            if (idx == -1) // ak je property ne roote a nema zavnoreny ziaden serializovany objekt
            {
                return property.serializedObject.FindProperty(condHAtt.SourceField);
            }
            else // ak je serilizovany field hlboko zavnoreny v pod classach
            {
                propertyPath = propertyPath.Substring(0, idx);
                return property.serializedObject.FindProperty(propertyPath).FindPropertyRelative(fieldName);
            }
        }

all my solution find in attachments

3830992–323230–ConditionalHide.zip (2.31 KB)

2 Likes

I have a very similar problem but a tad more complicated. Assume my code is this:

[System.Serializable]
public class Child {
public int num = 5;
public bool myBool = true;
}
public class Parent : MonoBehaviour {
public Child[ ] child = new Child[10];
}

How would that Parent editor script go in order for me to access each element of my child?
Thank you for your time in advance

@A_Savvidis

Your child class is not marked as serializable…

“How would that Parent editor script go in order for me to access each element of my child?”

What part you have problem with?

You should get the “child” array as serialized property in your editor script then you can iterate the array values with the help of serialized property’s array size and array elements and render them as you wish.

1 Like

Thank you for the response @eses I wanted to write sooner but I had some projects to deliver.
That’s what I was going for but couldn’t make it because I never worked so much with serialised properties but finally reading what you wrote I knew I was on the right path and pushed more I managed to do it (with FindPropertyRelative which I never had used before) and here is how in case anyone is facing the same issue with me.

I did this:
EDITOR:

SerializedProperty[ ] child_num_Serialized;
SerializedProperty[ ] child_myBool_Serialized;

void OnEnable()
{
child_Serialized = serializedObject.FindProperty("child");

for (int i = 0; i < 10; i++)
{
child_num_Serialized *= child_Serialized.GetArrayElementAtIndex(i).FindPropertyRelative("num");*
<em>child_myBool_Serialized *= child_Serialized.GetArrayElementAtIndex(i).FindPropertyRelative("myBool");*</em>
_*}```*_
_*so now I can create my inspector with the usual:*_
<em><em>```child_myBool_Serialized*.boolValue = EditorGUILayout.Toggle("this is my bool here:",myTarget.*</em></em>
<em><em>_child*.myBool); ```*_</em></em>
<em><em>_*Thank you for your time eses!*_</em></em>
2 Likes

@A_Savvidis

Np - and a note - I’m not sure if you know or not, but there’s also PropertyField, that renders/draws any serialized property automatically with its default look (saves you some repetitive typing):

2 Likes

Nice tip there. Thank you mate. You are alright… then again you do use an avatar from “the day the earth stood still” so it’s easy to assume you are a cool person.

Also let me give an example to summarise since there are too many. Here I am putting Unity Events from a subclass array to custom editor inspector.

public class MainClass: MonoBehaviour
{
    [Serializable]
    public class SubClass
    {
        public UnityEvent endEvent;
    }

    [SerializeField]
    public List<SubClass> eventList = new List<SubClass>();
}



[CustomEditor(typeof(MainClass))]
class MainClassEditor : Editor
{
    private MainClass _script;
    private void OnSelection()
    {
       if (!_script) _script = (MainClass)target;
    }

     public override void OnInspectorGUI()
     {
          this.serializedObject.Update();
          for (int segment = 0; segment < _script.eventList.Count; segment++)
          {
               SerializedProperty eventProperty = this.serializedObject.FindProperty("eventList").GetArrayElementAtIndex(segment).FindPropertyRelative("endEvent");
               EditorGUILayout.PropertyField(eventProperty);
          }
          this.serializedObject.ApplyModifiedProperties();
      }
}
1 Like