Exposing A ScriptableObject Array Using Custom Inspector?

Hello, After numerous Google searches and trial and error I have not been able to expose the variables within a ScriptableObject while they are in an array.

I’m trying to write a custom inspector for a monobehavior that has an array of ScriptableObjects and for them to be exposed in the monobehavior’s inspector, I have made sure the ScriptableObject class is serializable.

I have also looked at this and tried to modify it using arrays of editors but with no luck.

Do I have to write a custom PropertyDrawer for the ScriptableObjects before I can expose them in an array?

Any help is appreciated.

No need for a PropertyDrawer. You should be able to show the array in an inspector without any special tricks. Have you tried using Unity - Scripting API: EditorGUILayout.PropertyField?

For example, if the name of your array field is “arrayOfObjects”, you could do the following in your inspector:

SerializedObject so = base.serializedObject;
so.UpdateIfDirtyOrScript();

EditorGUILayout.PropertyField(so.FindProperty("arrayOfObjects"), true);

so.ApplyModifiedProperties();

The custom inspector doesn’t seem to be able to find the property, is there something I have to do in the ScriptableObject class for this to work?

Currently all my ScriptableObject class is this:

 [Serializable]
    public class MyScriptableObject : ScriptableObject
    {
        public int testInt = 0;
    }

My monobehavior class:

public class MyMonobehavior: Monobehavior
{
    List<MyScriptableObject> arrayOfObjects;
}

And the custom editor:

[CustomEditor(typeof(MyMonobehavior))]
    public class MyMonobehaviorsEditor : Editor
    {
        public override void OnInspectorGUI()
        {

            SerializedObject so = base.serializedObject;
            so.UpdateIfDirtyOrScript();

            EditorGUILayout.PropertyField(so.FindProperty("testInt"), true);

            so.ApplyModifiedProperties();
           
        }
    }
}

There are two problems:

  • Your “arrayOfObjects” is not serialized. Either make it public or add “SerializeField” attribute.
  • MyMonobehaviour does not have a field called “testInt”, you need to get the “arrayOfObjects” instead.

EDIT: Sorry! Just read your original post again and I had somehow misunderstood your goal. You were supposed to show the fields within the assets instead of just showing the assets themselves. -.-

EDIT #2: Anyway, you can get the inner properties like this:

var list = so.FindProperty("arrayOfObjects");
var element = property.GetArrayElementAtIndex(someIndex);
EditorGUILayout.PropertyField(element.FindPropertyRelative("testInt"), true);

hmm, I feel like you are giving me code without context. Are you suggesting that I create a propertyField for an element I find with FindProperty, if so where should I put this code? Am I writing this in the custom inspector and getting the list of ScriptableObjects from the monobehavior the CustomInspector is for or do I need to do something in the scriptableObject class itself to expose its properties in the Custom Inspector?

The Unity documentation is really vague and their code example threw a bunch of errors so I might need an explanation of propertyFields since I never used them.

And to clarify I have a GameObject with a monobehavior attached to it, it has a list of ScriptableObjects but they are just the greyed out boxes with the name of the asset, I would like to be able to show all the variables that are in the scriptable object for the instance in that array via a CustomInspector.

So here is the solution I came up with:

MyMonobehaviour targetMonobehaviour = (MyMonobehaviour)target;

            for(int i = 0; i < targetMonobehaviour.myList.Count; i++)
            {
                if(targetMonobehaviour.myList[i] != null)
                {
                    CreateEditor(targetMonobehaviour.myList[i]).OnInspectorGUI();
                }
            }

I might try and make it a foreach statement since the for statement was left over from other code I was testing but this seemed to work.

If you want to show your ScriptableObject’s default inspector replace OnInspectorGUI() with DrawDefaultInspector(), using OnInspectorGUI() will draw any custom inspectors you have written for your ScriptableObject.

Note: These are not instanced so any changes made on one of the scriptable objects will change the values on all of them, luckily I think this works for my purposes.

I probably should have posted this in Unity answers hehe.

Edit: The not null check is redundant, it is just there because I have not made a way to remove objects from the list yet and there were some leftover null spots.

Edit #2: Note: this should only run once, or we keep creating a new editor over and over.