PropertyDrawer for list. Subclass item fields not showing. Help needed!
Asked Answered
H

3

0

Confusing title, I know… Here’s what I mean:
I’m trying to draw a list of objects of the class Action. Every element in the list is a different type of subclass of Action (for example Idle, Leap or Wait). The problem is that I want to modify the specific values of these subclasses but their fields are currently not showing up when I use the Editor.propertyField(property: action, includeChildren: true).
147027-unity-2019-10-04-19-55-18.png

This is what I want:
147028-unity-2019-10-04-20-22-03.png
I think the reason for this problem is I’m using a List<Action> for storing my subclasses. Thus the property automatically assumes all objects are of class Action (which only has one public variable “privateName”) and not the subclasses Wait, Idle or Leap. Is there any way to draw all of the fields of the subclass when having them in a list?
I’m currently using a Reorderable list to draw my actions and am currently calling Editor.propertyField(property: action, includeChildren: true) on each and every one to display them. This is the code i use to create my list.
public List<Action> actionList = new List<Action>();

Hidebound answered 3/1 at 13:47 Comment(0)
H
0

Custom serializable classes do not support inheritance and polymorphism when it comes to serialization. Such classes are always serialized based on the field type. No type information is stored in the serialized data.

Please read this page carefully

CustomEditors or Property drawers can only change how the data is presented. You can not change the way how it’s serialized.

There are ways to implement custom serialization logic by implementing the ISerializationCallbackReceiver interface. However it’s only meant to convert things that can not be serialized into data that can be serialized.

Hemianopsia answered 3/1 at 13:46 Comment(1)

I'm not very used to using unity answers so I had to make my comment into an "answer". I have clarified my question inside that answer, so please check it out. :)

Hidebound
H
0

@Hemianopsia
Thanks for your answer. Though it doesn’t quite answer my question, but I don’t think I made myself clear enough, so I’ll try again. I will try to show you the behavior I want and what I am currently getting from a simple example.

TLDR can be found at the bottom.

Let’s say we have a script QAction (The Q doesn’t stand for anything, it’s just there to not interfere with my other scripts).

[System.Serializable]
public class QAction
{
        [HideInInspector]
        public string actionName = "Empty Action";
        public string privateName = "";

        public virtual void Act()
        {
            Debug.Log("(" + actionName + ") Somebody called me!");
        }
}

Then we have two subclasses of QAction. QWalk and QJump.

[System.Serializable]
public class QWalk : QAction
{
    public float speed = 10f;
    public float duration = 15f;

    public QWalk()
    {
        actionName = "Walk";
    }

    public override void Act()
    {
        Debug.Log("(" + actionName + ") is walking!");
    }
}

[System.Serializable]
public class QJump : QAction
{
    public float jumpHeight = 5f;
    public float airTime = 2f;

    public QJump()
    {
        actionName = "Jump";
    }

    public override void Act()
    {
        Debug.Log("(" + actionName + ") Jumped!");
    }
}

Now let’s say I want a property drawer for QWalk (To keep this simple I’ll just add some extra space below the property).

[CustomPropertyDrawer(typeof(QWalk))]
public class QWalkDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.PropertyField(position, property, includeChildren: true);
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return EditorGUIUtility.singleLineHeight * 7f;
    }
}

Everything works as intended, I can see my property and there is some extra space below it (see picture below). Now let’s say I want to make a nice propertydrawer for a list of actions, so I create a script for the QActionList and a QActionListDrawer.

[System.Serializable]
public class QActionList
{
    public QAction[] actionList = new QAction[3] { new QWalk(), new QJump(), new QAction() };
}

[CustomPropertyDrawer(typeof(QActionList))]
public class QActionListDrawer : PropertyDrawer
{
    SerializedProperty list;
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        list = property.FindPropertyRelative("actionList");
        EditorGUI.PropertyField(position, list, includeChildren: true);
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return EditorGUIUtility.singleLineHeight * 10f;
    }
}

Let’s also create a simple container where we can view how the different drawers look.

public class QTestContainer : MonoBehaviour
{
    public QJump jumpAction;
    public QWalk walkAction;
    public QActionList actionList;
}

But when I view the script in the inspector I get the following…

We can see that the two first elements (Jump Action and Walk Action) are being drawn correctly, but in the list both the Jump and Walk actions are missing fields. Thus I cannot access the values of Walk and Jump because (I suspect) the array only draws the fields inherited from QAction. How can I fix this (or work around it) so that I easily can edit the different actions when inside an array or list?

TLDR: For some reason when drawing the actions using a list, Unity only draws the fields of the base class QAction instead of drawing them as in the picture above “Jump Action” and “Walk Action” which is the way I want them to be displayed inside of the array “Action List”.

Hidebound answered 6/6, 2023 at 4:24 Comment(0)
G
0

This may be an old thread. but there is now a way to view a list of classes with different inherited subclasses. You need to use the attribute [field: SerializeReference] also you need to have custom editor buttons to add the different subtypes.

Gilbart answered 3/1 at 16:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.