How to make a deep copy of a list of ScriptableObject derived types?

The structure of my game is pretty unusual, so I’ll give some context first. I’m working on a little puzzle / maze game, where pretty much every object can be moved / modified.

I handle this in the following way: every one of my objects inherits from a base class called RotatableObject, which in turn inherits from ScriptableObject (is required to use polymorphism when serializing assets). Then, using the scene view and a custom mapEditorScript, I can add objects of my choice to a list rotatableObjectList.

When hitting play, I can play the puzzle and after stopping, the puzzle resets, which is what I want (I have a script that translates the rotatableObjectList into prefabs that it instantiates). The problem starts when I save the map. I use another ScriptableObject derived class called Map, that contains a list of RotatableObject, and some other puzzle / map specific information. using:

Map newMap = ScriptableObject.CreateInstance();
newMap.map = new List (rotatableObjectList);
//...
AssetDatabase.CreateAsset(newMap,path);
for (int i = 0; i < newMap.map.Count; i++) { AssetDatabase.AddObjectToAsset(newMap.map, path); }
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();

Saving and loading the map works, but after the map is saved, any changes that are made in play mode (by simply playing the game) are persistent, as the map ScriptableObject keeps being re-serialized. What I need is a to make a deep copy of the rotatableObjectList, and save that, so that the saved list is never changed, while the “active” in-game list can be.

I’ve looked at EditorUtility.CopySerialized(original, copy), but for this to work the original and the copy need to be of the same type, and I can’t know the type of the RotatableObject derived class beforehand. Trying to find the type and then use it as a type (not as a variable) to create a copy object of the correct type led me to dynamic variables, which, if I understand correctly, are not implemented in Unity.

I can think of two other ways to make deep copies: one is to write a function that checks a given RotatableObject for the type by comparing it to all the possible derived classes in a long if else chain, and then returns an object of that type which can be used to copy the original object to.
Another solution could be to implement a Copy function manually in all the derived classes, which is responsible for creating a new instance of the class, giving in the correct parameters and then returning the new object.

Both of these methods seem error prone with respect to adding new objects, and involve writing extra code. So I was wondering, is there an easy way to make a deep copy of ScriptableObjects (of unknown type) that I’m not aware of? Or is there a clever way to use EditorUtility.CopySerialized(original, copy)?

Thanks in advance!

Well in general you can create a copy of any UnityEngine.Object derived class (which includes ScriptableObjects as well) by using Instantiate. However it depends on what you understand by “deep copy”. It will clone all serializable class instances that the scriptable object might contain. However it won’t clone any objects referenced by the serialized object which are UnityEngine.Object derived themselfs. So if your scriptable object references a material, GameObject, [ … ] or another scriptable object the clone will also references those objects. If you want to create an instance of those as well you have to instantiate them manually.

Your question doesn’t contain much details about your class and which types are involved so it’s impossible to give any more detailed advice. If you need more information you should include your class declaration in your question.