When you create a new State in an Animator Controller, you can add new StateMachineBehaviours to it. Those StateMachineBehaviours are actually ScriptableObjects.
I’d like to re-create a similar editor. Is there an easy way?
The way I’m thinking sounds pretty complicated:
User creates a new “My Scriptable Object Container”
Draw a button on the “My Scriptable Object Container” that when clicked, reflects on all Assemblies and finds all types that inherit “My Scriptable Object Behaviour”.
When button is clicked, draw a pop up list similar to the one when clicking on “Add Behaviour” (not sure how to even do that…)
Create a new instance of the scriptable object and use AssetDatabase.AddObjectToAsset to and the HideInEditor flag if required.
Draw a context menu (don’t know how to do this either) so the user can remove the asset behaviour.
I seem to remember there being some internal popup in the editor that’s more flexible than this, but you can get pretty far with a normal popup set to a button-like skin. Quick example:
Note that there’s nothing in this that implies that the things you’re creating and adding to the main asset needs to be ScriptableObjects. That you want to hide them implies to me that they probably just need to be [Serializable] classes in a list on the main asset.
What do you mean here? Do you want to lay out the attached behaviour with a remove button? Or?
To draw the things added, you can either do that manually in the editor code you created the popup in (easy, have to manually take care of undo), or create a CusomPropertyDrawer and use PropertyFields to draw them (hard, cumbersome)
Yes its possible, but there is no “easy” way… it will be a heck of a lot of coding.
Agreed, I don’t think you necessarily need to call AssetDatabase.AddObjectToAsset. if you plan on only referencing them internally within the root’s scope, you should be able to simply CreateInstance on command and then let Unity Serialize it. when the root object is loaded again Unity “should” automatically deserialize the sub ScriptableObject instances, create them and link them up again.
if you were planning on referencing them externally, then AddObjectToAsset would make sense. The perfect example here are spritesheets. The root object is the full raw image, complete with its import settings and a list of all the sprites. which then has child Sprite instances that can be directly referenced elsewhere in the project.
Unity’s Inspectors uses EditorGUI.DropdownButton() (on line 1342) calling an internal class (AddComponentWindow) to actually draw the content inside the dropdown. You can use the GenericMenu class instead or implement your own AddComponentWindow class.
He means to recreate the “Context Menu” button that you see in the inspector for a component.
@ , By default this is handled by the Editor Class’s OnHeaderGUI which will call EditorUtility.DisplayObjectContextMenu (an internal function) you could just as easily use a GenericMenu instead. building it statically (i.e. hardcoding) is very straightforward, but if you want the same level of flexibility as the built-in then you’ll need to put in some reflection to dynamically load in MenuItem attributes with a “CONTEXT/” path
Wow this is exactly what I meant and exactly what I’m been doing so far (in regards to the GenericMenu) but it doesn’t look as nice. It seems like a lot of work to re-implement and make it look nice.
Yes, they will only be referenced internally within the root’s scope, but it doesn’t seem like Unity is serializing the scriptable object until I create an asset of it. Not sure if maybe my code is wrong maybe. Everything works fine if I create assets out of them tho.
The reason I use ScriptableObject over [Serializable] classes is to handle polymorphism since the list could contain different subtypes.