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:
- 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.
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.
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