Get asset file from scriptableobject (Nested Scriptableobjects)

####Edit 2:
Ok i think i found the issue: When OnEnable is called the actual asset isnt created, it is created AFTER OnEnable. So you cant nest Scriptable Objects into a scriptable after creating an container asset :confused:

####EDIT1:
Is it possible to get the asset file of an scriptable object in its OnEnable method?

####ORIGINAL:
Hi, im playing around with Scriptable Objects. But I’m running into multiple errors. Most of the code and examples i can find only are 2+ years old.

I was trying some basic thing, basicly a linked list: I have an mono behaviour holding a reference on a Container, which has a reference on a child (and each child has a child reference too, …)


1st Try

[Serializable][CreateAssetMenu]
public class Container : ScriptableObject{
    [SerializeField] public Child root; // Child derives from ScriptableObject
    public void OnEnable() {
        if (root == null) {
            root = CreateInstance<Child>();
}   }   }

At this point i’ve run into my first error: type missmatch . Well I see why i happens: The Child instance is created but isn’t saved anywhere (Maybe someone can explain it better than me).


2nd Try

But i want the childs to live inside this container, and not everyone getting an own file.

[Serializable][CreateAssetMenu]
public class Container : ScriptableObject{
    [SerializeField] public Child root; // Child derives from ScriptableObject
    public void OnEnable() {
        if (root == null) {
            root = CreateInstance<Child>();
            AssetDatabase.AddObjectToAsset(root, this);
            AssetDatabase.SaveAssets();
}   }   }

Now I’ve got the error:

AddAssetToSameFile failed because the other asset is not persistent

I’ve googled for that error, but this error seems to be rare :confused:


So, how would one do something like that?

Scriptable objects needs to be saved to file to be persistent. You do this through AssetDatabase.CreateAsset. So you want:

if (root == null) {
    root = CreateInstance<Child>();
    AssetDatabase.CreateAsset(child, "Path_To_Object");
    ... //as before
}

late to the party but i had the same issue and there is a relatively simple solution - search for the path of your object and check whether it’s null or empty:

[Serializable][CreateAssetMenu]
public class Container : ScriptableObject
{
    [SerializeField]
    public Child root;

    public void OnEnable() 
    {
        var path = AssetDatabase.GetAssetPath(this);
        if (string.IsNullOrEmpty(path))
        { return; }

        if (root == null) 
        {
            root = CreateInstance<Child>();
            AssetDatabase.AddObjectToAsset(root, this);
            AssetDatabase.SaveAssets();
        }
    }
}