Display Custom Inspectors for each class in a List<>

I’m not sure how to proceed with this, but I’ve been investigating PropertyDrawer and PropertyAttribute and I’m not sure if they’re going to work for what I want.

Here’s the setup:

public class ContainerClass : Monobehaviour
{
    public List<BaseBehavior> behaviors;

    public void AddToList(BaseBehavior b)
    {
        if(!behaviors.Contains(b))
            behaviors.Add(b);
    }
    ...
    public void BunchaFunctions() { //etc }

}
    [System.Serializable]
    public class BaseBehavior : ScriptableObject
    {
        public float force;
        public Vector3 direction;
    }

    [System.Serializable]    
    public class FirstBehavior : BaseBehavior
    {
        public float additionalForce;
        public float delayTime;
    }

    [System.Serializable]    
    public class SecondBehavior : BaseBehavior
    {
        public bool isStupendous;
        public Vector3 exampleVector;
    }

Here’s the loop in my editor class where I might expand / view each Behavior class:

ContainerObject control = target as ContainerObject ;
		int index = 0;
		foreach (BaseBehavior in control.behaviors)
		{	
			foldouts[index] = EditorGUILayout.Foldout(foldouts[index], behavior.ReportType().ToString());
			if (foldouts[index])
			{
				
				// this is where I assume display info goes? 
			}		
			index++;
		}

What I have so far is an Editor class that creates a custom inspector for ContainerClass. The custom inspector allows me to select and add various behavior types from my project to the List. All good so far. I can display the list of behaviors, but now I need to get into each Behavior and edit its parameters.

Normally this wouldn’t be a problem without a custom inspector, as you can just expand the list, look at each element and expand the available parameters that way. Unfortunately, implementing a custom inspector overrides that ability.

How can I get that back without coding an inspector for each class? Or at least making something general enough that it works for any new Behaviors written, regardless of what variables the new Behaviors might have (so long as they inherit from BaseBehavior). At this stage, it doesn’t necessarily need to be pretty, so long as the variables are accessible.

At some point I found myself delving into System.Reflection to pull apart each behavior and send back arrays of variables to be displayed. That seems like overkill, and presents its own world of problems.

What are my options in this scenario?

Thanks in advance

You can use Editor.CreateEditor(object) to get the actual, for-srs editor for an object. Then in your custom OnInspectorGUI, call each editor’s OnInspectorGUI.

I’ve got a couple snippets from my own “Another Inspector” which is sorta tied in to custom classes, but it gets the point across:

This is my EditorWindow’s ONGUI:

	public void OnGUI() {
		inspect = EditorGUILayout.ObjectField(inspect,typeof(UnityEngine.Object),true);
		if ( old != inspect || (null==editors && null!=inspect)) {
			if ( typeof(GameObject) == inspect.GetType() ) {
				editors = new AnInspector[0];
				foreach(UnityEngine.Object ob in (inspect as GameObject).GetComponents<Component>()) {
					editors = editors.With(new AnInspector(Editor.CreateEditor(ob)));
//					Debug.Log(editors[editors.Length-1].GetType().FullName);
				}
			} else {
				editors = new AnInspector[]{new AnInspector(Editor.CreateEditor(inspect))}; 
			}
		}
		
		if ( null != inspect && null != editors ) {
			using ( new GUIUtils.Scroll(ref scroll) ) {
				foreach(AnInspector editor in editors) {
					editor.OnInspectorGUI();
				}
			}
		}
		old = inspect;
	}

And this is AnInspector:

	private class AnInspector {
		public AnInspector(Editor e) { editor = e; }

		Editor editor;
		bool open=true;
		public void OnInspectorGUI() {
			GUIUtils.StyledFoldout(ref open, "Component: " + editor.target.GetType().Name.AsSpacedCamelCase(),()=>{
				editor.OnInspectorGUI();
			},"","");
//			},"serverupdatechangeseton");
//			},"tl selectionbutton predropglow");
			GUILayout.Button("",GUILayout.Height(1f));
		}
	}

GUIUtils just wraps things I find awkward to do all the time (like Begin/End Layout functions)

Here’s Scroll:

	public class Scroll : IDisposable {
		public Scroll(ref Vector2 scroll, params GUILayoutOption[] options) { scroll=GUILayout.BeginScrollView(scroll, options); }
		public Scroll(ref Vector2 scroll, string style, params GUILayoutOption[] options ) { scroll=GUILayout.BeginScrollView(scroll,style,options); }
		public Scroll(ref Vector2 scroll, GUIStyle style, params GUILayoutOption[] options ) { scroll=GUILayout.BeginScrollView(scroll,style,options); }
		public void Dispose() { GUILayout.EndScrollView(); }
	}

StyledFoldout’s more complex, but same concept, just wrapping layouting:

	public static void StyledFoldout(ref bool state, string text, EmptyDelegate function, string style = "box", string style2 = "textarea") {
		using ( new Vertical(style) ) {
			Foldout(ref state, text);
			if ( state )
				using ( new Indent() ) 
					using ( new Vertical(style2) ) 
						function();
		}
	}

Vertical and Indent are disposables like Scroll.

And Foldout:

	public static bool Foldout(ref bool open, GUIContent text ) {
		Init();
		if ( open ) { 
			if ( GUILayout.Button( text, openFoldoutStyle, GUILayout.Height(20) ) ) {
				GUI.FocusControl ("");
				GUI.changed = false; // force change-checking group to take notice
				GUI.changed = true;
				open = false;
			}
		} else {
			if ( GUILayout.Button( text, closedFoldoutStyle, GUILayout.Height(20) ) ) { 
				GUI.FocusControl ("");
				GUI.changed = false; // force change-checking to take notice
				GUI.changed = true;
				open = true;
			}
		}
		return open;
	}