这应该是一个相当简单的问题要解决,但是我已经尝试了几种方法,但结果总是一样的。
我试图将包含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);
}
}
}
我收到以下错误:
ArgumentException:类型必须是可序列化的参数名称: source:SP0(UnityEngine.GameObject)ObjectCopier.Clone [GameObject] (UnityEngine.GameObject源码)(at 资产/脚本/ 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");
}
}
现在,在这里创建原始列表:
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;
}
}
这&#34; tempObj&#34;有[SerializeField]属性所以我必须在这里遗漏一些东西。任何帮助将不胜感激。
编辑:忘记提及,这个应用程序在Unity3D中。答案 0 :(得分:2)
我认为您需要使用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);
}
}
我希望这会有所帮助。
编辑。也许是使用像
这样的东西没有序列化的深层拷贝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();
}
}
我刚刚发现Copyable使用反射来提供对象的深层副本。我再次希望这有用......
答案 1 :(得分:0)
使用Unity中的Instantiate
创建对象的完整副本,如下所述:http://docs.unity3d.com/Documentation/ScriptReference/Object.Instantiate.html?from=MonoBehaviour
var clone = Object.Instantiate(source);
答案 2 :(得分:0)
我认为我过于复杂化了事情,最终在XML文件中保存了我需要的值(游戏对象位置)(无论如何必须在某个时候执行)。谢谢你的帮助。