- Home /
Custom Inspector: Using 'serializedObject' to access inherited members
My desired behaviour is quite simple, yet has been very difficult to achieve. I am no guru at Unity serialization and thus I've been stuck for quite some time on this problem.
To put it plainly, I have a base class that I will call 'BaseClass' and a derived class called 'ChildClass'. BaseClass has many members that ChildClass inherits and uses, with very few of it's own members. None of which I need to see in the inspector. Thus I want to create a custom inspector for BaseClass that all derived classes can use including ChildClass.
Currently my classes are setup as follows:
[System.Serializable]
public abstract class BaseClass : Monobehaviour, CustomInterface1, CustomInterface2
{
public int m_customInterface1Implementation { get; protected set; }
public int m_customInterface2Implementation { get; protected set; }
public int m_baseClassMember;
}
[System.Serializable]
public class ChildClass: BaseClass
{
}
In my custom inspector I am attempting to access these like this:
[CustomEditor(typeof(BaseClass), true)]
public class BaseClassEditor : Editor
{
SerializedProperty m_inheritedProperty;
private void OnEnable()
{
m_inheritedProperty = serializedObject.FindProperty("m_customInterface1Implementation ")
}
public override void OnInspectorGUI()
{
m_inheritedProperty.objectReferenceValue = (Gameobject)EditorGUILaout.ObjectField("Object", m_inheritedProperty.objectReferenceValue, typeof(GameObject), true);
}
}
Now unless I'm simply using the property incorrectly, when I am attempting to use this inspector as is I get a NullReferenceException. This works however with members that are not inherited, so I am led to assume that I cannot access the members inherited from BaseClass from serializedObject directly.
Is it possible to access the inherited members of BaseClass from the serializedObject? I'm new to writing inspectors using serializedObject and SerializedProperties, I've only ever written them using the cast method.
[CustomEditor(typeof(BaseClass), true)]
public class BaseClassEditor : Editor
{
BaseClass m_baseClassReference;
private void OnEnable()
{
m_baseClassReference = (BaseClass)target;
}
}
However, it seems it is now preferred to write editors using serializedObject instead of the target cast method. More importantly though, I lose the ability to keep the class members private or protected while still being able to view them through the inspector (for monitoring) since the cast method can only allows regular access to the class you are inspecting.
Answer by Bunny83 · Nov 19, 2018 at 11:49 PM
Your issue has nothing to do with inheritance but with the simple fact that your two auto properties are not serialized. Unity does not serialize properties at all. Unity only serializes fields as long as they are public or marked with the SerializeField attribute. However the backing field of your auto properties is a private compiler generated field you don't have any access to.
Have a look at the script serialization documentation.
The next issue is that you used "objectReferenceValue" of the serializedProperty but (given that "m_customInterface1Implementation" actually is a field and not a property) it's actually of type int. For an int type you have to use SerializedProperty.intValue. Likewise "EditorGUILaout.ObjectField" only works for actual reference types that are derived from "UnityEngine.Object" (like Transform / Component, GameObject, Mesh, ...).
There's no issue using properties in your class, but if you want them to be serializable you need to use an explicitly declared backing field which you serialize. Keep in mind that Unity doesn't care about your properties at all. Unity only cares about your serializable fields
public abstract class BaseClass : Monobehaviour, CustomInterface1, CustomInterface2
{
[SerializeField]
private int m_BackingField1;
public int m_customInterface1Implementation { get{ return m_BackingField1;} protected set {m_BackingField1 = value;} }
[SerializeField]
private int m_BackingField2;
public int m_customInterface2Implementation { get{ return m_BackingField2;} protected set {m_BackingField2 = value;} }
public int m_baseClassMember;
}
public class ChildClass: BaseClass
{
}
Those classes have proper field that are serialized. Note that a custom editor can not change what fields are serialized or not. A custom editor just provides a custom way to present the serialized data to the user. Note when you want to create a custom editor for your class you can only read / write the backing fields, not the properties.
You might have confused Untiy's "SerializedProperty" with an actual "C# property". They have nothing in common and belong to completely different things.
I really appreciate the detailed answer, my apologies for responding a month late. Seems I disabled email notifications and never realized I received an answer!
I actually haven't had the time to come back to this problem yet, but when I do I think I have a better idea of where to start up again, thanks!
Seems however, I won't be able to get my desired functionality which is to access private variables through the inspector in a way that ignores access modifiers (as if everything is public). I'll have to come up with a different approach I suppose. Thanks again!
Your answer
Follow this Question
Related Questions
Error when trying to Serialize a field that is in a class 0 Answers
Replicate "Apply" and "Revert" button functionality in ScriptableObject Editor Inspector 2 Answers
Why are the children of my Serialized Property not being drawn? 1 Answer
Finding property with serializedObject on script with a generic 0 Answers