Scriptableobject Instantiate, cloning sub-assets

I’m using a ScriptableObject as a “prefab” for a class. I’ve saved the ScriptableObject on a .asset file together with some sub-assets.

Calling ScriptableObject.Instantiate on the parent asset succesfully clones the object with no problems.

However, the child objects are not cloned, so all the copies created with ScriptableObject.Instantiate are referencing the same child objects in the original .asset file.

Looking at Object.Instantiate in the documentation shows this;
“When you clone a GameObject or Component, all child objects and components will also be cloned with their properties set like those of the original object.”

A scriptable object is neither a GameObject nor a Component, so it’s pretty much working as intended.
I am wondering if there is an other way to do it, manually cloning each child object is not very flexible :frowning:

1 Like

You need to do a deep clone, which, unfortunately, means manually cloning children. The only way around this would be reflection, which I wouldn’t recommend, since there’s a lot of extra overhead, and you lose a lot of control over the process.

If this is for an editor script you can use EditorUtility.CopySerialized:

Obviously this won’t work for runtime code. I remember running into this problem on one of my projects and I moved over to using normal prefabs. This isn’t ideal but it can make things a lot easier.

I need this in runtime, but knowing how to do it in the editor is good to know, thanks.
I could use a prefab, but it feels kind of messy to create a container component/gameobject just for a class.

I’ll just do it manually I guess, everything I want to clone resides in lists, so I can at least automate it somewhat.
Thanks!

A ScriptableObject wouldn’t have any child objects. To have children, it’d have to have a Transform to relate those children. That’s what the documentation about Object.Intantiate is referring to… all the GameObjects and components attached to them, that are inside the base GameObject are also cloned.

Are you talking about fields/properties on the ScriptableObject that reference other GameObjects? Those aren’t children, those are fields that reference another object.

Using reflection isn’t that slow. Sure if you’re doing this constantly, it could become slow, but if you’re instantiating once, it’s not a big deal.

Is there some reason you must use ScriptableObject? Why can’t it be a component attached to a GameObject? Do note though, if you make it a component on a GameObject, and these “children” are just fields on the component, it still won’t clone them (unless it happens to be referencing a gameobject within its own hierarchy of the prefab, in which case… yes it will reference the new clone).

1 Like