- Home /
Showing member ScriptableObject's in the Inspector
Suppose I have a MonoBehavior which has a public member inherited from ScriptableObject. How can I display the editor for the member object in the same Inspector window that shows the MonoBehavior itself?
What I have
This is the situation in more detail. I have my own asset class inherited from ScriptableObject' like this: public class MyAsset : ScriptableObject { public int param1 = 1; public int param2 = 2; public int param3 = 3; } I have an instance of MyAsset` in the Assets folder, and I can edit it in the Inspector: 
So far so good. But now I want to use this asset in my MonoBehavior's. Here is a MonoBehavior descendant:
public class MyBehavior : MonoBehaviour {
public MyAsset memberAsset;
}
Now this is what Inspector looks like when editing a GameObject that has MyBehavior attached to it: 
What I want
You see, I can set memberAsset to point to MyAsset instance of my choosing, but if I want to edit the asset itself, I have to do it separately. Is there a way to display an editor for MyAssetInstance below, in the same editor window?
Example that shows it should be possible
As you can see in the same Inspector window, my GameObject has a MeshRenderer component, and that component has in its members a Material. Now the editor for the material appears right below, so you can edit it in place, without losing focus of the GameObject. There must be a way to make MyBehavior-MyAsset pair behave the same as MeshRenderer-Material. My guess is that I want to make a custom Editor for MyBehavior, but I can't find any methods in EditorGUILayout that would allow me to spawn a new Editor for MyAsset and show it below in the same inspector window. Any help?
@BigRoy It was a long time ago. As far as I remember, I wasn't able to reproduce the behavior of $$anonymous$$eshRenderer-$$anonymous$$aterial pair exactly.
Answer by Johat · Aug 20, 2015 at 07:39 PM
Hey, don't know if you managed to figure this out, but I think CreateEditor or CreateCachedEditor are what you're after. CreateCachedEditor seemed to be the cleanest and simplest implementation.
So if you have a MonoBehaviour:
using UnityEngine;
public class MyBehaviour : MonoBehaviour
{
public MyAsset MemberAsset;
// Note: assets don't need to be public for it to work
[SerializeField] private MyAsset _memberAsset;
}
Where MyAsset derives from ScriptableObject (for example -- but any Object should be okay).
You could create something like this (for example):
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(MyBehaviour))]
public class MyBehaviourEditor : Editor
{
private Editor _editor;
public override void OnInspectorGUI()
{
serializedObject.Update();
var myAsset = serializedObject.FindProperty("MemberAsset");
CreateCachedEditor(myAsset.objectReferenceValue, null, ref _editor);
_editor.OnInspectorGUI();
serializedObject.ApplyModifiedProperties();
}
}
(Obviously, you could play with the other functions that can be called on editors here too.)
Note that, it will draw the inspector just as it would if you had it in the inspector. You may not want this (e.g. may not want the script field to display), so you can supply a custom editor that will do the job. In fact, you could write as many editors as you wanted and select which editor will be used as the second parameter (we passed null here, which will just give you the default editor for that Object).
Hope that's what you were after =).
I searched for hours trying to find the answer to this, it was exactly what I was after.
Answer by TheVastBernie · Jul 22, 2017 at 04:27 PM
If anyone's still wondering and wants a general solution that works for every scriptable object, without needing to write custom inspectors, you can take a look at the post over here: https://forum.unity3d.com/threads/editor-tool-better-scriptableobject-inspector-editing.484393/
It takes a custom property drawer for ScriptableObjects to display every derived class within the main inspector of the MonoBehaviour.
This was simple and helped me. Thank you for referring to that thread!
Answer by as3mbus · Nov 15, 2019 at 10:24 AM
https://gist.github.com/tomkail/ba4136e6aa990f4dc94e0d39ec6a058c
in case someone still looking for a way to do this
Answer by hatuf · Jul 19, 2013 at 08:24 AM
One way for such a simple class would be to add getters and setters to MyBehavior that would access the memberAssets properties.
public int param1
{
get
{
return memberAsset.param1;
}
set
{
memberAsset.param1 = value;
}
}
This is an interestind idea, but I have a feeling that if $$anonymous$$yAsset grows more complex, this can quickly get out of hand. Also, it's not clear how to adjust the approach if ins$$anonymous$$d of a single $$anonymous$$yAsset $$anonymous$$yBehavior contained, say, a List of them with unknown length.
Answer by JohnnySunshine · Jul 19, 2013 at 09:55 AM
Mark MyAsset as serializable and it will show up in the inspector nicely.
[System.Serializable]
public class MyAsset : ScriptableObject
{
}
No, it doesn't work that way. If $$anonymous$$yAsset didn't inherit from ScriptableObject, then it would work, but then $$anonymous$$yAsset wouldn't be a separate asset, it would be basically just a structure inside of $$anonymous$$yBehavior. And I want it to be a separate asset.
Oh, you're right, sorry. That slipped my $$anonymous$$d somehow. (Do I remove this answer, or just wait for others to downvote it?)
Your answer