store the data of a game object instead of referencing it (got a 16 day deadlin need help)

ok, so I have gotten pretty far without personally asking a question on the forum, so here it is.

I want to kill my game object in a specific way, whilst respawning it.
I reset the hp on the game object,
and then call
useForRespawn[//this stores the data of the object] = this.gameObject;

I set a few more values,
do the broadcast message and send the gameobj with it.
I then kill the original obj.

MY PROBLEM:
the gameobject variable isn’t storing the data of the gameobject, it is referencing it.
so when I edit some vars later in the script, it edits the vars of useForRespawn as well.

MY QUESTION:
how do I stop that?
I need to be able to use this.gameObject to collect the data,
but I want to be able to store that data instead of reference it.
the stored data stays the same as your body ragdolls, and once the timer runs out,
it respawns/kills the original.
I need to keep most of the code the same, so if you want to post a workaround like using a prefab, don’t.

thanks guys.

It sounds like you need to deep copy your objects, and you can do that in a few ways. First, you can create a class constructor that takes the object type as a parameter and copies all the fields in the constructor when creating the new object. You can also serialize an object and then restore that to another object variable or you can use reflection with recursion to copy the fields. Here’s what an implementation of the deep copy constructor might look like:

public class MyObject
{
    private int myVar1 = 0;
    private int myVar2 = 0;

    public MyObject() { }

    public MyObject(MyObject copiedObj)
    {
        this.myVar1 = copiedObj.myVar1;
        this.myVar2 = copiedObj.myVar2;
    }
}

//To use:
MyObject main = new MyObject();
MyObject copy = new MyObject(main);

Please post answers as answers and comments as comments.

Here is a method that lets your create a deep copy of any instance. The first CopyObjectData method is generally sufficient.

using System;
using System.Reflection;//for copying objects
using System.Linq;//for string[].Contains()
using UnityEngine;//for print

public class CopyData {
	
	/// <summary>
	/// Copies the data of one object to another. The target object gets properties of the first. 
	/// Any matching properties (by name) are written to the target.
	/// </summary>
	/// <param name="source">The source object to copy from</param>
	/// <param name="target">The target object to copy to</param>
	public static void CopyObjectData(object source, object target)
	{
		CopyObjectData(source, target, String.Empty, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
	}
	
	/// <summary>
	/// Copies the data of one object to another. The target object gets properties of the first. 
	/// Any matching properties (by name) are written to the target.
	/// </summary>
	/// <param name="source">The source object to copy from</param>
	/// <param name="target">The target object to copy to</param>
	/// <param name="excludedProperties">A comma delimited list of properties that should not be copied</param>
	/// <param name="memberAccess">Reflection binding access</param>
	public static void CopyObjectData(object source, object target, string excludedProperties, BindingFlags memberAccess)
	{
		string[] excluded = null;
		if (!string.IsNullOrEmpty(excludedProperties))
		{
			excluded = excludedProperties.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		}
		
		MemberInfo[] miT = target.GetType().GetMembers(memberAccess);
		
		foreach (MemberInfo Field in miT)
		{
			string name = Field.Name;
			
			// Skip over excluded properties
			if (string.IsNullOrEmpty(excludedProperties) == false
			    && excluded.Contains(name))
			{
				continue;
			}
			
			
			if (Field.MemberType == MemberTypes.Field)
			{
				FieldInfo sourcefield = source.GetType().GetField(name);
				if (sourcefield == null) { continue; }
				
				object SourceValue = sourcefield.GetValue(source);
				((FieldInfo)Field).SetValue(target, SourceValue);
			}
			
			else if (Field.MemberType == MemberTypes.Property)
			{
				PropertyInfo piTarget = Field as PropertyInfo;
				PropertyInfo sourceField = source.GetType().GetProperty(name, memberAccess);
				if (sourceField == null) { continue; }
				
				if (piTarget.CanWrite && sourceField.CanRead)
				{
					object targetValue = piTarget.GetValue(target, null);
					object sourceValue = sourceField.GetValue(source, null);
					
					if (sourceValue == null) { continue; }
					
					if (sourceField.PropertyType.IsArray
					    && piTarget.PropertyType.IsArray
					    && sourceValue != null ) 
					{
						CopyArray(source, target, memberAccess, piTarget, sourceField, sourceValue);
					}
					else
					{
						CopySingleData(source, target, memberAccess, piTarget, sourceField, targetValue, sourceValue);
					}
				}
			}
			
		}
	}
	
	private static void CopySingleData(object source, object target, BindingFlags memberAccess, PropertyInfo piTarget, PropertyInfo sourceField, object targetValue, object sourceValue)
	{
		//instantiate target if needed
		if (targetValue == null
		    && piTarget.PropertyType.IsValueType == false
		    && piTarget.PropertyType != typeof(string))
		{
			if (piTarget.PropertyType.IsArray)
			{
				targetValue = Activator.CreateInstance(piTarget.PropertyType.GetElementType());
			}
			else
			{
				targetValue = Activator.CreateInstance(piTarget.PropertyType);
			}
		}
		
		if (piTarget.PropertyType.IsValueType == false
		    && piTarget.PropertyType != typeof(string))
		{
			CopyObjectData(sourceValue, targetValue, "", memberAccess);
			piTarget.SetValue(target, targetValue, null);
		}
		else
		{
			if (piTarget.PropertyType.FullName == sourceField.PropertyType.FullName)
			{
				object tempSourceValue = sourceField.GetValue(source, null);
				piTarget.SetValue(target, tempSourceValue, null);
			}
			else
			{
				CopyObjectData(piTarget, target, "", memberAccess);
			}
		}
	}
	
	private static void CopyArray(object source, object target, BindingFlags memberAccess, PropertyInfo piTarget, PropertyInfo sourceField, object sourceValue)
	{
		int sourceLength = (int)sourceValue.GetType().InvokeMember("Length", BindingFlags.GetProperty, null, sourceValue, null);
		Array targetArray = Array.CreateInstance(piTarget.PropertyType.GetElementType(), sourceLength);
		Array array = (Array)sourceField.GetValue(source, null);
		
		for (int i = 0; i < array.Length; i++)
		{
			object o = array.GetValue(i);
			object tempTarget = Activator.CreateInstance(piTarget.PropertyType.GetElementType());
			CopyObjectData(o, tempTarget, "", memberAccess);
			targetArray.SetValue(tempTarget, i);
		}
		piTarget.SetValue(target, targetArray, null);
	}
}