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!