serialize a scriptableObject containing a custom class

Say I got a custom class A:

[System.Serializable]
public class A
{
    public int a;
    public int b;
}

And I want to store it into a scriptableObject B:

[System.Serializable]
public class B : ScriptableObject
{
    public int a = 2;
    public A[] aArray;

    public void OnEnable()
    {
        if(aArray == null)
        {
            aArray = new customClass[a];
        }
        // if A inherent from scriptable Object, initialize like this
//        for(int i = 0; i < a; ++i)
//        {
//            if(aArray[i] == null)
//                aArray[i] = ScriptableObject.CreateInstance<A>();
//        }
    }
}

And I want to edit the data of B in an editor:

[CustomEditor(typeof(B))]
public class BEditor : Editor
{
    private SerializedObject _obj;
    private SerializedProperty _aArray;
    public void OnEnable()
    {
        _obj = new SerializedObject(target);
        _aArray = _obj.FindProperty("aArray");

        // if A is a normal class, the following two ways generates error
        _aArray.GetArrayElementAtIndex(0).objectReferenceValue = new A();
        (A)_aArray.GetArrayElementAtIndex(0).objectReferenceValue = new A();

        // if A inherent from scriptableObject, after the following assignment the content becomes null
        Debug.Log(_aArray.GetArrayElementAtIndex(0).objectReferenceValue);
        _aArray.GetArrayElementAtIndex(0).objectReferenceValue = ScriptableObject.CreateInstance<A>();
        Debug.Log(_aArray.GetArrayElementAtIndex(0).objectReferenceValue);
        //  this line gives error: the left-hand side should be a property
        (A)_aArray.GetArrayElementAtIndex(0).objectReferenceValue = ScriptableObject.CreateInstance<A>();
    }
}

How do I access the aArray in B?
I’ve searched the community for a while, yet not finding any answers.

  1. can A simply be a normal class?
  2. if A has to inherent from scriptableObject, how to assign value to it? I tried the following way but it only gets null:
    _aArray.GetArrayElementAtIndex(0).objectReferenceValue = ScriptableObject.CreateInstance();

Any answer or link is greatly appreciated:)

For serialization purposes, ‘A’ can be any class that can be serialized. Including own classes with the “Serializable” attribute. If you mark a class with the “Serializable” attribute you also have to make sure that all of its contents are serializable as well (or mark stuff that shouldn’t be serialized with the “NonSerialized” attribute).
I’m not exactly sure what you mean with accessing “aArray in B”… Since it’s a public field you can simply write bInstance.aArray, where bInstance is an instance of B (created with var bInstance = ScriptableObject.CreateInstance();)

1 Like

After you’ve marked your classes as System.Serializable, you can access properties from within an Editor script by using this method: Unity - Scripting API: SerializedObject.FindProperty

I’m sorry for the confusion, the problem comes when I try to assign new values to aArray, here’s the code:

    private SerializedObject _obj;
    private SerializedProperty _aArray;

    public void OnEnable()
    {
        _obj = new SerializedObject(target);
        _aArray = _obj.FindProperty("aArray");

        // if A is a normal class, I can't assign value to it like this
       _aArray.GetArrayElementAtIndex(0).objectReferenceValue = new A();
        // nor this one
       (A)_aArray.GetArrayElementAtIndex(0).objectReferenceValue = new A();

        // if A inherent from scriptableObject, after such assigning it becomes null
       Debug.Log(_aArray.GetArrayElementAtIndex(0).objectReferenceValue);
        _aArray.GetArrayElementAtIndex(0).objectReferenceValue = ScriptableObject.CreateInstance<customClass>();
       Debug.Log(_aArray.GetArrayElementAtIndex(0).objectReferenceValue);
        // and something like this says the left-hand should be a property
       (A)_aArray.GetArrayElementAtIndex(0).objectReferenceValue = ScriptableObject.CreateInstance<A>();

I marked [System.Serializable] already and everything else works fine (built in type) but my custom class.

I found a way and A can be a normal class:

[CustomEditor(typeof(B))]
public class BEditor : Editor
{
    private B _targetB;
    public void OnEnable()
    {
        _targetB = (B)target;
    }

    public override void OnInspectorGUI()
    {
        _targetB.aArray[0] = new A();
    }
}

But how to assign it with SerializedProperty still remains a myth to me, and since I can do it this way, what is the purpose of SerializedProperty? I thought I can only serialize things with them.