- Home /
Copy the values of a class instance to another instance of the same class
Hi. I need to copy the values of a class instance to another instance of that same class. I want to do something like:
MyClass class1;
MyClass class2;
class1.x = 1;
class1.y = 2;
class2 = class1; // The problem here is that class1 is passed by reference
I was hoping that after assigning class1 to class2, I can get class2's x and y fields to have 1 and 2 respectively. So basically, I want to pass a class by value.
Thanks!
Answer by dannyskim · Sep 06, 2012 at 05:15 AM
Typically, you'll either want to do a 'shallow copy' or a 'deep copy' when copying fields from one instance of a class to another instance of the same class type.
A shallow copy is when say class1 and class2 share the same memory address, so whatever you change on one object will change on the other.
What you're probably looking for is a deep copy, where the fields are ACTUALLY copied / cloned to the destination instance. Since this isn't really Unity specific, you should try and access the wealth of knowledge that the MSDN and similar communities have to offer:
Cloning Objects in C#:
http://stackoverflow.com/questions/78536/cloning-objects-in-c-sharp
Another route you could take is using .NET Reflection, which is a bit more complicated but will get the job done just as well.
Answer by fafase · Sep 06, 2012 at 05:26 AM
Depending on the members you have, if you only have a couple of variables, you could use a struct instead. In C#, structures are passed by value.
Other way could be to use a function that return the class:
class Dog
{
int age;
int size;
public Dog(int a = 10, int s = 20) {
age = a;
size = s;
}
public Dog GetDog() {
//Dog d = new Dog(this.age,this.size);
//return d;
return this;
}
Dog one = new Dog(100,100);
Dog two =new Dog();//Default constructor two has value 10 and 20
two = one.GetDog();
//now two has the value of one 100 and 100.
EDIT:just remove the two lines from the function as it can be done faster.
Answer by SheepHugger · Aug 21, 2013 at 12:41 PM
This is an old thread, but there's a simple answer to this:
class Rabbit
{
var speed : int = 10;
var name : String = "Hare";
function Clone(hare : Rabbit)
{
hare.speed = speed;
hare.name = name;
}
}
var Rabbit1 = new Rabbit();
var Rabbit2 = new Rabbit();
Rabbit1.name = "Roger";
Rabbit2.name = "Jolly";
Debug.Log(Rabbit1.name + " | " + Rabbit2.name);
// Prints "Roger | Jolly"
Rabbit2.Clone(Rabbit1);
Debug.Log(Rabbit1.name + " | " + Rabbit2.name);
// Prints "Jolly | Jolly"
Rabbit2.name = "Roger";
Debug.Log(Rabbit1.name + " | " + Rabbit2.name);
// Prints "Jolly| Roger "
So you see, we can have the cloning of variables function inside a class and the values will not be references but independent. Also, having the clone function inside the class makes maintenance straightforward.
That doesn't exactly work actually - if for instance you changed Rabbit1.name after then clone, then Rabbit2 will also have the same update, which is not desired. It's also much more complicated and onerous if you have real objects that need to be deep copied.
Well, I tried it before posting it here and it worked. Did you actually try it out?
The whole point of my solution lies in assigning the values directly, so they're not references.
It also supports very complex classes, you just need a lot longer list of instructions for Clone()
Oops - yep, you are right 8) String is not mutable so you can't change it. But any kind of reference class that is mutable (pretty much everything else) would require a proper deep copy.
For instance:
class Rabbit
{
var speed : int = 10;
var name : String = "Hare";
var mesh : $$anonymous$$esh; //$$anonymous$$utable
var someArray : String[]; //$$anonymous$$utable
var hash : HashTable; //$$anonymous$$utable
var aComponent : SomeComponent; //$$anonymous$$utable
function Clone(hare : Rabbit)
{
hare.speed = speed;
hare.name = name;
}
}
Yes, thank you whydoidoit! I failed to call upon that - anyone using this should notice that for example if you wish to copy a link to a GameObject, you should be linking towards the prefab object and not an instanced object unless you know what you're doing.
I personally am working on something with a lot of data driven class object instances for simulation and this is an ideal way to multiply these objects (create new instances based on existing variations). Very low maintenance and with my limited knowledge this seems like a nice solution.
For these question/answer topics it is of utmost importance to point out important details that are missed. Sometimes we fail to recognize the value of a lesson because we've learnt it so well - such as this thing whydoidoit brought up about mutable classes - and then the people who utilize these threads as resource material (myself included) will not gain as much as they could.
Answer by JOKaija · Oct 23, 2016 at 10:55 AM
I know, this is an old question, but when I try to figure out how to do it, I saw this msg too. There is a SIMPLE solution:
Using Json:
[Serializable]
public class _buildingInfo
{
public String stringtext;
public GameObject gobject;
}
public _buildingInfo buildingInfo1;
public _buildingInfo buildingInfo2 = new _buildingInfo();
buildingInfo2 = JsonUtility.FromJson<_buildingInfo>(JsonUtility.ToJson(buildingInfo1));
This is a neat way of doing it, but sadly it only appears to grab public variables only. Static, private etc will be ignored which totally sucks.
The JsonUtility will serialize the object with (almost) the same rules as the normal serialization system in Unity. So if you want to serialize private variables you have to mark them with the SerializeField attribute.
Static fields are completely unrelated. No serialization system will ever serialize static variables as they do not belong to the class instance. Static variables can't be accessed through an instance reference from outside. They can only be accessed through the class name.
Answer by Max_Bol · Nov 11, 2020 at 07:05 AM
Personally, to avoid any form of issues that the JsonUtility might create along the road, I went with a semi-manual way of handling a deep copy of a serialized field.
It become something like this (for a custom serialized "Options" Field) :
public static void CopyOptions(OptionsData To, OptionsData From)
{
To = new OptionsData();
To.Language = From.Language;
To.Volume_Main = From.Volume_Main;
To.Volume_Menu = From.Volume_Menu;
To.Volume_Music = From.Volume_Music;
To.Volume_Sounds = From.Volume_Sounds;
To.Volume_Voices = From.Volume_Voices;
To.Difficulty = From.Difficulty;
To.KidMode = From.KidMode;
To.isWindowed = From.isWindowed;
To.ScreenResolutionMultiplier = From.ScreenResolutionMultiplier;
To.ShadowQuality = From.ShadowQuality;
To.AntiAliasing = From.AntiAliasing;
To.VSyncCount = From.VSyncCount;
To.SoftParticleActive = From.SoftParticleActive;
}
[Serializable]
public class OptionsData
{
public int Language = 0;
public float Volume_Main = 1f;
public float Volume_Music = 0.8f;
public float Volume_Sounds = 1f;
public float Volume_Voices = 1f;
public float Volume_Menu = 1f;
[Range(1,3)]
public int Difficulty = 1;
public bool KidMode = false;
public bool isWindowed = false;
[Range(0, 4)]
public int ScreenResolutionMultiplier = 2;
[Range(0, 2)]
public int ShadowQuality = 2;
[Range(0, 2)]
public int AntiAliasing = 2;
[Range(0, 4)]
public int VSyncCount = 4;
public bool SoftParticleActive = true;
}
While it takes a bit of time to setup, the good thing is that you can reuse it anywhere and feed what you need. I simply have to use the function CopyOptions(A,B) to fill A's data with a copy of B's data.