CustomEditor : DrawDefaultInspector for Class

Heya, I am to making a CustomEditor for one of my scipts.

I have a enum in my script, and it is getting nicely displayed in the inspector.
What I want is the inspector to show different classes based on the enum.

For example:
I choose the enum: spawnEnemy → want to show the SpawnEnemyScript in the inspector.
or
I choose the enum: wait → want to show the WaitXSecondsScript in the inspector.

I have no problems checking which enum there currently is selected.
My problem is I don’t want to make a custom view for all the different scripts that can be choosed.

I am looking for a function like DrawDefaultInspector(), just for another script than the CustomEditor for the script I am currently showing.

I'm not exactly sure what you're trying to achieve here. It seems like you are trying to create a script which then controls what other scripts run on your Game Object via an enum - am I correct in understanding this?

Glad to see I was understanding. This actually kind of breaks Unity's convention of having a different behaviour per script. What you're doing is creating a script, which would have to be a MonoBehaviour and thus exist at run-time, be strictly an Editor object. Do you want to have all of these classes be behaviours of this game object and you're just switching, or do you only want one of these on there at a time and switching the enum value in your inspector would remove the old behaviour and replace it with a new one?

1 Answer

1

I think I get what you’re asking, but I’m still left asking “why?”:

Inspectors by default only draw for MonoBehaviour derivatives, because only a MonoBehaviour can be attached as a Component to a GameObject.

What you’re doing here is actually really going against Unity’s grain and you’re definitely making life harder for yourself.

The fact that you are calling a class “BaseAction” leads me to believe that it is the foundation class for a number of various actions that will be performed. In Unity, an “action” could probably be used synonymously with “behaviour” - which is why the whole MonoBehaviour class structure pretty much single-handedly drives Unity’s API. It just seems to me like you are needlessly reinventing the wheel on this, is all.

With that said - only MonoBehaviours can be shown in the Inspector, but you can use the Editor API to script out custom editors for each one of these classes.

If you were to stick with this route though, here’s probably the simplest way to do it:

  1. LevelScript the MonoBehaviour has a property called action, which is a BaseAction. (The BaseAction class must be a SerializableAttribute)

  2. Each additional action must extend BaseAction.

  3. Use your custom inspector to set the value of the target LevelScript’s action to the class corresponding to the enum, remember to destroy old references.

  4. Depending on the action that is selected, you can draw inspector fields to edit it’s properties. You can do this manually in a case switch because you will know what all the important properties are - or maybe use something like System.Reflection to traverse the class’s properties and spit out fields.

It’s a lot of work, which is why I suggest re-evaluating your approach to take advantage of Unity’s power.

[Edit]
The way I typically handle this Level Manager:

I will generally create an empty GameObject and name it “Managers” and I will attach various MonoBehaviour classes to this GameObject. (ie a class called LevelManager)

Then, any simple actions that are clearly defined will be attached to this same GameObject, or other GameObjects parented to the “Managers” (it depends on how many behaviours it needs) For instance I’ll have one for spawning enemies, pickups, etc. which has reference to the objects that need to be spawned and they will contain the encapsulated logic for spawning them.

The LevelManager will have a reference to all of these other managers, so all you have to do is communicate with the level manager to update data and get things happening.

It makes for very small management classes that only serve one purpose and are very maleable.

Hope that helps.

==

The player/end user won't see that GameObject as it isn't being rendered. GameObjects are simply containers that do nothing on their own but bundled with Components (MonoBehaviour) drive the entire engine. I do all of my "Level Managers" this way - it is very extensible and extremely powerful. It is something that takes some getting used to, but once you are used to it, it really just makes sense. In any case, I provided a sort of overview about how you'd get non-MonoBehaviour objects drawing in your Inspector. Give it a shot if you're still looking to do it that way. Cheers!

revised answer

I revised my answer to include the explanation you asked for. My revision is marked as "[Edit]"

I don't know - I typically don't use GetComponetsInChildren when they have to be in any specific order. What you could do is in the script that would be grabbing that array, just have a public ActionBase[] array and manually set it in the inspector. By caching these you save cpu cost in the expensive hierarchy traversal and component lookups.

In my previous comment I'm assuming that the amount of those components won't ever change.