Get asset file from scriptableobject (Nested Scriptableobjects)
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 :/
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 :/
So, how would one do something like that?
Answer by Baste · Nov 11, 2015 at 02:38 PM
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
}
what is child?
did you mean root
? If so: this solution does not work.
To create the container as asset file i use the [CreateAsset$$anonymous$$enu] attribute. Why do i need CreateAsset? the asset file exists, which is the reason OnEnable is called.
and i want to add the root object to this existing asset file. Based on the documention it should not be necessary to create the subasset with createAsset
Answer by tbriley · Sep 17, 2017 at 08:52 AM
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();
}
}
}
Your answer
Follow this Question
Related Questions
ScriptableObject not saving to Asset properly 0 Answers
LoadAssetAtPath doesn't seem to work for ScriptableObject asset in AssetPostProcessor 1 Answer
How can I get a sub asset? 1 Answer
ScriptableObject Instances Referencing One Set of Prefabs - Changing One SO Changes The same prefab 1 Answer
How to "Lock" scriptable objects from losing their [SerializeField] values 0 Answers