列表的深层副本

use*_*217 5 c# list deep-copy unity-game-engine

这应该是一个相当简单的问题要解决,但是我已经尝试了几种方法,但结果总是一样的.

我正在尝试将包含GameObjects的列表复制到另一个列表中.问题是我似乎正在复制引用,因为对原始列表的GameObjects所做的任何更改也会影响新列表中的那些,这是我不想发生的事情.从我所读到的,我正在做一个浅拷贝而不是深拷贝,所以我尝试使用以下代码来克隆每个对象:

public static class ObjectCopier
    {
        /// <summary>
        /// Perform a deep Copy of the object.
        /// </summary>
        /// <typeparam name="T">The type of object being copied.</typeparam>
        /// <param name="source">The object instance to copy.</param>
        /// <returns>The copied object.</returns>
        public static GameObject Clone<GameObject>(GameObject source)
        {

            if (!typeof(GameObject).IsSerializable)
            {
                throw new ArgumentException("The type must be serializable ", "source: " + source);
            }

            // Don't serialize a null object, simply return the default for that object
            /*if (Object.ReferenceEquals(source, null))
            {
                return default(GameObject);
            }*/

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            using (stream)
            {
                formatter.Serialize(stream, source);
                stream.Seek(0, SeekOrigin.Begin);
                return (GameObject)formatter.Deserialize(stream);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

ArgumentException:类型必须是可序列化的参数名称:source:SP0(UnityEngine.GameObject)ObjectCopier.Clone [GameObject](UnityEngine.GameObject source)(在Assets/Scripts/ScenarioManager.cs:121)

上面发布的函数在这里调用:

    void SaveScenario(){
        foreach(GameObject obj in sleManager.listOfSourcePoints){
            tempObj = ObjectCopier.Clone(obj);

            listOfScenarioSourcePoints.Add(tempObj);
            Debug.Log("Saved Scenario Source List Point");
        }
        foreach(GameObject obj in sleManager.listOfDestPoints){
            tempObj = ObjectCopier.Clone(obj);
            listOfScenarioDestPoints.Add(tempObj);
            Debug.Log("Saved Scenario Dest List Point");
        }
    }

    void LoadScenario(){
        sleManager.listOfSourcePoints.Clear();
        sleManager.listOfDestPoints.Clear ();
        foreach(GameObject obj in listOfScenarioSourcePoints){
            tempObj = ObjectCopier.Clone(obj);
            sleManager.listOfSourcePoints.Add(tempObj);
            Debug.Log("Loaded Scenario Source List Point");
        }
        foreach(GameObject obj in listOfScenarioDestPoints){
            tempObj = ObjectCopier.Clone(obj);
            sleManager.listOfDestPoints.Add(tempObj);
            Debug.Log("Loaded Scenario Dest List Point");
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在,在这里创建原始列表:

if (child.name == "DestinationPoints")
{
     parentDestinationPoints = child.gameObject;
     foreach (Transform grandChildDP in parentDestinationPoints.transform)
     {
          //Debug.Log("Added DP object named: " + grandChildDP.name);
          tempObj = grandChildDP.gameObject;
          listOfDestPoints.Add(tempObj);
          tempObj.AddComponent<DestinationControl>();
          tempObj.transform.renderer.material.color = Color.white;
     }
}

// Hide all SourcePoints in the scene
if (child.name == "SourcePoints")
{
    parentSourcePoints = child.gameObject;
    foreach (Transform grandChildSP in parentSourcePoints.transform)
    {
         tempObj = grandChildSP.gameObject;
         listOfSourcePoints.Add(tempObj);
         tempObj.transform.renderer.enabled = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

这个"tempObj"有[SerializeField]属性,所以我必须在这里遗漏一些东西.任何帮助将不胜感激.

编辑:忘了提,这个程序是在Unity3D.

Moo*_*ght 3

我认为您需要标记GameObject您尝试使用该[Serializable]属性克隆的类。我还将使克隆方法变得通用,以便它不限于类型:

/// <summary>
/// Creates a deep clone of an object using serialization.
/// </summary>
/// <typeparam name="T">The type to be cloned/copied.</typeparam>
/// <param name="o">The object to be cloned.</param>
public static T DeepClone<T>(this T o)
{
    using (MemoryStream stream = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, o);
        stream.Position = 0;
        return (T)formatter.Deserialize(stream);
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助。


编辑。也许是一个没有序列化的深层复制,使用类似的东西

class A
{
    // copy constructor
    public A(A copy) {}
}

// A referenced class implementing 
class B : IDeepCopy
{
    object Copy() { return new B(); }
}

class C : IDeepCopy
{
    A A;
    B B;
    object Copy()
    {
        C copy = new C();

        // copy property by property in a appropriate way
        copy.A = new A(this.A);
        copy.B = this.B.Copy();
     }
}
Run Code Online (Sandbox Code Playgroud)

我还刚刚发现Copyable它使用反射来提供对象的深层副本。再次,我希望这有一些用处......