CustomPropertyDrawer with UnityEvent

I am trying to work around the difficulties of inheritance and the Inspector. My current thought is to have a Custom Property Drawer for my type and a drop-down list that defines which data the Inspector shows. However I am getting some very strange results.

// ActionList is a container of CompanyActions
[System.Serializable]
public class BaseAction : UnityEvent<ActionList> { }

[System.Serializable]
public class CompanyAction
{
    public BaseAction action;
}


[CustomPropertyDrawer(typeof(CompanyAction))]
public class CompanyActionDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty(position, label, property);
EditorGUI.PropertyField(position, property.FindPropertyRelative(“action”));
EditorGUI.EndProperty();
}
}
The final result is definitely broken. I cannot collapse any of the UnityEvent types, and the height of the PropertyDrawer is not being calculated correctly:

Any ideas on where to go from here?

I am total new (I don’t consider my self even beginer) in editor scripting but recently I had to change some standard assets scripts to fit my needs. I saw there property drawers are used in some scripts e.g. waypoint circuit script. Below is that portion of the script.

namespace UnityStandardAssets.Utility.Inspector
{
#if UNITY_EDITOR
    [CustomPropertyDrawer(typeof(WaypointCircuit.WaypointList))]
    public class WaypointListDrawer : PropertyDrawer
    {
        private float lineHeight = 18;
        private float spacing = 4;


        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            EditorGUI.BeginProperty(position, label, property);

            float x = position.x;
            float y = position.y;
            float inspectorWidth = position.width;

            // Draw label


            // Don't make child fields be indented
            var indent = EditorGUI.indentLevel;
            EditorGUI.indentLevel = 0;

            //var items = property.FindPropertyRelative("itemsGo");
            //var titles = new string[] { "Waypoints", "", "", "" };
            //var props = new string[] { "waypoints", "^", "v", "-" };
            var widths = new float[] { .7f, .1f, .1f, .1f };
            float lineHeight = 18;
            //bool changedLength = false;
            //if (items.arraySize > 0)
            //{
            //    for (int i = 0; i < items.arraySize; i++)
            //    {
            //        var item = items.GetArrayElementAtIndex(i);

            //        float rowX = x;
            //        for (int n = 0; n < props.Length; ++n)
            //        {
            //            float w = widths[n] * inspectorWidth;

            //            // Calculate rects
            //            Rect rect = new Rect(rowX, y, w, lineHeight);
            //            rowX += w;

            //            if (i == -1)
            //            {
            //                EditorGUI.LabelField(rect, titles[n]);
            //            }
            //            else
            //            {
            //                if (n == 0)
            //                {
            //                    EditorGUI.ObjectField(rect, item.objectReferenceValue, typeof(GameObject), true);
            //                }
            //                else
            //                {
            //                    if (GUI.Button(rect, props[n]))
            //                    {
            //                        switch (props[n])
            //                        {
            //                            case "-":
            //                                items.DeleteArrayElementAtIndex(i);
            //                                items.DeleteArrayElementAtIndex(i);
            //                                changedLength = true;
            //                                break;
            //                            case "v":
            //                                if (i > 0)
            //                                {
            //                                    items.MoveArrayElement(i, i + 1);
            //                                }
            //                                break;
            //                            case "^":
            //                                if (i < items.arraySize - 1)
            //                                {
            //                                    items.MoveArrayElement(i, i - 1);
            //                                }
            //                                break;
            //                        }
            //                    }
            //                }
            //            }
            //        }

            //        y += lineHeight + spacing;
            //        if (changedLength)
            //        {
            //            break;
            //        }
            //    }
            //}
            //else
            //{
            //    // add button
            //    var addButtonRect = new Rect((x + position.width) - widths[widths.Length - 1] * inspectorWidth, y,
            //                                 widths[widths.Length - 1] * inspectorWidth, lineHeight);
            //    if (GUI.Button(addButtonRect, "+"))
            //    {
            //        items.InsertArrayElementAtIndex(items.arraySize);
            //    }

            //    y += lineHeight + spacing;
            //}

            // add all button
            var addAllButtonRect = new Rect(x, y, inspectorWidth, lineHeight);
            if (GUI.Button(addAllButtonRect, "Assign using all child objects"))
            {
                var circuit = property.FindPropertyRelative("circuit").objectReferenceValue as WaypointCircuit;
                
                if (circuit.waypointCubePrefab != null && circuit.waypointCubes.Count == 0)
                {

                    var children = new GameObject[circuit.transform.childCount];
                    
                    for(int i=0; i < circuit.transform.childCount; i++)
                    {
                        children *= circuit.transform.GetChild(i).transform.gameObject;*

}
//foreach (Transform child in circuit.transform)
//{
// children[n++] = child;
//}
// Array.Sort(children, new TransformNameComparer());
int n = 0;
circuit.waypointList.itemsGo = new GameObject[children.Length];
for (n = 0; n < children.Length; ++n)
{
circuit.waypointList.itemsGo[n] = children[n].transform.gameObject;
}
circuit.ConvertWaypointsToCubes();
}
else
{
Debug.LogWarning(“Either there are no way points or prefab is null or the Waypoints are already assigned.”);
}
}
y += lineHeight + spacing;

// show/hide cubes button
var showHideCubesButtonRect = new Rect(x, y, inspectorWidth, lineHeight);
if (GUI.Button(showHideCubesButtonRect, “Show/Hide Waypoint Cubes”))
{
var circuit = property.FindPropertyRelative(“circuit”).objectReferenceValue as WaypointCircuit;
circuit.ShowHideCubes();
}
y += lineHeight + spacing;

// show/hide numbers button
var showHideNumbersButtonRect = new Rect(x, y, inspectorWidth, lineHeight);
if (GUI.Button(showHideNumbersButtonRect, “Show/Hide Waypoint Numbers”))
{
var circuit = property.FindPropertyRelative(“circuit”).objectReferenceValue as WaypointCircuit;
circuit.ShowHideWaypointNumbers();
}
y += lineHeight + spacing;

// rename all button
var renameButtonRect = new Rect(x, y, inspectorWidth, lineHeight);
if (GUI.Button(renameButtonRect, “Auto Rename numerically from this order”))
{
var circuit = property.FindPropertyRelative(“circuit”).objectReferenceValue as WaypointCircuit;
int n = 0;
foreach (Transform child in circuit.waypointList.items)
{
child.name = "Waypoint " + (n++).ToString(“000”);
}
}
y += lineHeight + spacing;

// correct Child Objects Rotation button
var correctWaypointsRotationButton = new Rect(x, y, inspectorWidth, lineHeight);
if (GUI.Button(correctWaypointsRotationButton, “Correct WayPoints Rotations”))
{
var circuit = property.FindPropertyRelative(“circuit”).objectReferenceValue as WaypointCircuit;
circuit.MakeWaypointsRotationAlongRoute();
}
y += lineHeight + spacing;

// spawn prefab button
var spawnPrefabButtonRect = new Rect(x, y, inspectorWidth, lineHeight);
if (GUI.Button(spawnPrefabButtonRect, “Spawn Traffic Spawners Along Route”))
{
var circuit = property.FindPropertyRelative(“circuit”).objectReferenceValue as WaypointCircuit;
circuit.SpawnPrefabAlongRoutes();
}
y += lineHeight + spacing;

// destroy mesh renderers button
var destroyMeshRendererButtonRect = new Rect(x, y, inspectorWidth, lineHeight);
if (GUI.Button(destroyMeshRendererButtonRect, “Remove Mesh Renderers from waypoints Permanently”))
{
var circuit = property.FindPropertyRelative(“circuit”).objectReferenceValue as WaypointCircuit;
circuit.DestroyMeshRenderers();
}
y += lineHeight + spacing;

// Set indent back to what it was
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
}

public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
SerializedProperty items = property.FindPropertyRelative(“items”);
float lineAndSpace = lineHeight + spacing;
return 150 + (items.arraySize * lineAndSpace) + lineAndSpace;
}

// comparer for check distances in ray cast hits
public class TransformNameComparer : IComparer
{
public int Compare(object x, object y)
{
return ((Transform)x).name.CompareTo(((Transform)y).name);
}
}
}
#endif
There I faced similar issue when height was not adjusted properly and I changed the value (You can see there is written 150 near to bottom lines. Increasing this line helped me. As I said, I don’t have much idea of all this but this helped me. And I was basically wanting to have buttons in the inspector so that I could run my monoscript functions in editor mode… For that I found a Free tool BUTTON INSPECTON on unity asset store. You can go through the above example to check how it is adjusting height and using property drawer.
PS : I wanted to put this as comment instead of answer but unity answers did not let me exceed more than 3000 characters so I had to put it as answers.