Copying ScriptableObjects

Is there any way to simulate the copy semantics of MonoBehaviour in ScriptableObjects?

Let's say I have MonoBehaviour like this:

public class DummyClassBehaviour : MonoBehaviour { public DummyClass DummyClassTest; //ScriptableObject public DummyClassBehaviour DummyBehaviourTest; //Another DummyClassBehaviour } 

And ScriptableObject:

 public class DummyClass : ScriptableObject { public string Text = ""; } 

When I duplicate (CTRL + D) the GameObject application w / DummyClassBehaviour, "DummyBehaviourTest" copies, as expected: if it refers to MonoBehaviour in GameObject, which I copy, the copy engine updates the link to the same MonoBehaviour, enter a new GameObject. If it refers to MonoBehaviour in another GameObject, that link remains unchanged.

The ScriptableObject environment, on the other hand, always refers to the original. So I ended up with N GameObject all using the same ScriptableObject (DummyClass) from the original GameObject. I use ScriptableObjects to enable serialization of data classes other than Monobehaviour.

+4
source share
1 answer

As far as I can tell, and please someone correct me, if I'm wrong, you cannot change the serialization behavior of the ScriptableObject to match what it was in MonoBehaviour. Namely, that it should update links if a duplicate is created.

Instead, I chose a less optimal solution, but it works. My class is assigned a unique identifier that becomes serialized, like everything else. I use this identifier in DummyBehaviour.Awake () to create a lookup table, which I can then use to reassign my DummyClass.

I am not going to accept my own answer because I do not feel that it fully answers my original question, but it is related:

 [System.Serializable] public class DummyClass { // Unique id is assigned by DummyBehaviour and is unique to the game object // that DummyBehaviour is attached to. public int UniqueID = -1; public string Text = ""; // Override GetHashCode so Dictionary lookups public override int GetHashCode(){ int hash = 17; hash = hash * 31 + UniqueID; return hash; } // override equality function, allows dictionary to do comparisons. public override bool Equals(object obj) { if (object.ReferenceEquals(obj, null))return false; DummyClass item = obj as DummyClass; return item.UniqueID == this.UniqueID; } // Allow checks of the form 'if(dummyClass)' public static implicit operator bool(DummyClass a) { if (object.ReferenceEquals(a, null)) return false; return (a.UniqueID==-1)?false:true; } public static bool operator ==(DummyClass a, DummyClass b) { if (object.ReferenceEquals(a, null)) { return object.ReferenceEquals(b, null); } return a.Equals(b); } public static bool operator !=(DummyClass a, DummyClass b) { if (object.ReferenceEquals(a, null)) { return object.ReferenceEquals(b, null); } return !a.Equals(b); } } 

And my MonoBehaviour:

 [ExecuteInEditMode] public class DummyBehaviour : MonoBehaviour { public List<DummyClass> DummyClasses = new List<DummyClass>(); // reassign references based on uniqueid. void Awake(){ Dictionary<DummyClass,DummyClass> dmap = new Dictionary<DummyClass,DummyClass>(); // iterate over all dummyclasses, reassign references. for(int i = 0; i < DummyClasses.Count; i++){ DummyClass2 d = DummyClasses[i]; if(dmap.ContainsKey(d)){ DummyClasses[i] = dmap[d]; } else { dmap[d] = d; } } DummyClasses[0].Text = "All items same"; } // helper function, for inspector contextmenu, to add more classes from Editor [ContextMenu ("AddDummy")] void AddDummy(){ if(DummyClasses.Count==0)DummyClasses.Add(new DummyClass{UniqueID = 1}); else { // Every item after 0 points to zero, serialization will remove refs during deep copy. DummyClasses.Add(DummyClasses[0]); } UnityEditor.EditorUtility.SetDirty(this); } } 
+2
source

All Articles