How to break reference from .asset classes and runtime copied values?
Hello, I have an issue with the .assets files I created through a editor extension I made myself. Basically I create in a base class, a List containing my objects. These are complex objects containing other variables that get their value from other .asset files (in the editor), everything is serialized of course. Everything works fine, I can perform all the operations both in the editor and in game. The problem is that even if when I start the game I copy the values of the base List in an array with CopyTo, any change I make to any variable in the object is saved to the .asset file. Moreover, if I add the same object multiple times in the array and modify one of them, every object that uses the same variable changes accordingly. What I would like to do is: 1) to break the link between instantiated objects in game and the .asset database 2)break the link between objects that use the same value for a variable (coming from another .asset file), so that if I modify a variable in one object the changes do not propagate to the other objects.
I am afraid I was not clear enough but any help is appreciated.
Answer by Adam-Mechtley · Oct 27, 2016 at 07:13 AM
Hi @asters! If I understand correctly, you need to:
- Assuming your .asset is a ScriptableObject of some kind, you need to call Instantiate() when your game starts to create a duplicate. Make any run-time modifications on the duplicate rather than on the source asset. 
- You need to make sure that when you assign the same item to multiple different list indices that it is a copy. If the list element is a value type (e.g., float, int, struct) this is automatic. If it is a reference type (e.g., any class object) then you need to make sure you are assigning a copy. If the elements are a subclass of UnityEngine.Object, do the same as step 1 for each duplicated element. If they are a custom class of some kind, then you need to do something like make them ICloneable or otherwise copy any necessary data to a new instance. 
Answer by Zankaster · Oct 27, 2016 at 06:13 PM
Thank you, I was able to solve my problem and I learned something in the process while doing so, thank to your explanation. Basically what I needed was a so called "Deep Copy" of my main Class. You can do it as you said, making the classes ICloneable and implementing a symple Clone() function for them to make a copy without reference of the variables, so with a main function that did that starting from the outer class and going down to all referenced objects. I used a more lazy but quite effective approach, using this helper function: using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary;
 /// <span class="code-SummaryComment"><summary></span>
 /// Provides a method for performing a deep copy of an object.
 /// Binary Serialization is used to perform the copy.
 /// <span class="code-SummaryComment"></summary></span>
 public static class ObjectCopier
 {
     /// <span class="code-SummaryComment"><summary></span>
     /// Perform a deep Copy of the object.
     /// <span class="code-SummaryComment"></summary></span>
     /// <span class="code-SummaryComment"><typeparam name="T">The type of object being copied.</typeparam></span>
     /// <span class="code-SummaryComment"><param name="source">The object instance to copy.</param></span>
     /// <span class="code-SummaryComment"><returns>The copied object.</returns></span>
     public static T Clone<T>(this T source)
     {
         if (!typeof(T).IsSerializable)
         {
             throw new ArgumentException("The type must be serializable.", "source");
         }
 
         // Don't serialize a null object, simply return the default for that object
         if (Object.ReferenceEquals(source, null))
         {
             return default(T);
         }
 
         IFormatter formatter = new BinaryFormatter();
         Stream stream = new MemoryStream();
         using (stream)
         {
             formatter.Serialize(stream, source);
             stream.Seek(0, SeekOrigin.Begin);
             return (T)formatter.Deserialize(stream);
         }
     }
 }
It serializes your Object (Class, List, etc.) and deserializes it into a new Object, so you get a fresh copy of everything, free of any reference. The only drawback is that every class must be tagged serializable, but in my case I had to add it for just a couple of them. Here is the source of this script for anyone who will stumble into my same problem: http://www.codeproject.com/Articles/23832/Implementing-Deep-Cloning-via-Serializing-objects
Your answer
 
 
              koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                