Saving nested data with AssetDatabase.CreateAsset

Hi.

I got a nested structure of ScriptableObjects which I want to save and load from an .asset file.

So, I basically do this:

var bla = ScriptableObject.CreateInstance<Bla>();
bla.TheList.Add(ScriptableObject.CreateInstance<Bla2>());
bla.TheList.Add(ScriptableObject.CreateInstance<Bla2>());

var fileName = EditorUtility.SaveFilePanelInProject("Save effect", "1.asset", "asset", "");
AssetDatabase.CreateAsset(bla, fileName);

Where Bla and Bla2 are the following simple classes:

[Serializable]
class Bla : ScriptableObject
{
    public float A = 1;

    [SerializeField]
    public List<Bla2> TheList = new List<Bla2>();
}

[Serializable]
class Bla2 : ScriptableObject
{
    public float B = 3;
}

But the problem is that the list of Bla2 doesn’t get serialized automatically.
Trying to find a workaround I did the following:

foreach (var bla2 in bla.TheList)
{
    AssetDatabase.AddObjectToAsset(bla2, fileName);
}

And now data from the list gets serialized. But this was just an example. In real life I got lots of nested stuff inside the objects of the list which must be serialized too. So I’ll have to loop over all of them recursively using something like a visitor pattern or whatever.

What am I doing wrong? Is there a simpler way to do this?

Thanks.

Read Codingjargames.com. ScriptableObjects can only live in the scene or in an asset. The asset cannot reference ones created in the scene. You probably should ditch ScriptableObject and go with MonoBehaviours/Prefabs.

Otherwise you’re going to have to go through some more difficult stuff. You can write an Asset Post Processor that detects when something is saved. When an asset is saved, you can use reflection to loop through the fields, detect a reference to a ScriptableObject, and then AddObjectToAsset() on that reference.