Unity物件複製賦值給同類型的物件(克隆物件)
阿新 • • 發佈:2019-01-03
在把一個物件賦值給另外一個同類型的物件時,意味著兩個物件的堆疊資訊是一樣的。當你想把物件的某一個屬性更改後再新增到一個列表的時候,就會被最後的物件替換掉,就不能實現新物件的新增。下面兩種方式可以實現物件賦值給同類型的物件,這兩個物件的堆疊資訊是不一樣的。
方法一:
必須對物件進行序列化處理
public static object DeepClone(object obj) { BinaryFormatter bFormatter = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); bFormatter.Serialize(stream, obj); stream.Seek(0, SeekOrigin.Begin); return bFormatter.Deserialize(stream); }
測試:
[Serializable] class User { public User(){} public int id; public string name; public User(int id, string name) { this.id = id; this.name = name; } } public class test : MonoBehaviour { List<User> users; User user; // Use this for initialization void Start () { users = new List<User>(); user = new User(2,"小花"); } int b = 5; private void Update() { if (Input.GetKeyDown(KeyCode.Q)) { var a = new User(); a = GameTool.DeepClone(user) as User; a.id = b++; users.Add(a); } } }
方法二:
public static object CopyObject(object obj) { object targetDeepCopyObj; if (obj == null) { Debug.Log("copy obj is null"); } var targetType = obj.GetType(); //值型別 if (targetType.IsValueType == true) { targetDeepCopyObj = obj; } //引用型別 else { targetDeepCopyObj = Activator.CreateInstance(targetType); //建立引用物件 MemberInfo[] memberCollection = obj.GetType().GetMembers(); foreach (MemberInfo member in memberCollection) { if (member.MemberType == MemberTypes.Field) { FieldInfo field = (FieldInfo)member; object fieldValue = field.GetValue(obj); if (fieldValue is ICloneable) { field.SetValue(targetDeepCopyObj, (fieldValue as ICloneable).Clone()); } else { field.SetValue(targetDeepCopyObj, CopyObject(fieldValue)); } } else if (member.MemberType == MemberTypes.Property) { PropertyInfo myProperty = (PropertyInfo)member; MethodInfo info = myProperty.GetSetMethod(false); if (info != null) { object propertyValue = myProperty.GetValue(obj, null); if (propertyValue is ICloneable) { myProperty.SetValue(targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null); } else { myProperty.SetValue(targetDeepCopyObj, CopyObject(propertyValue), null); } } } } } return targetDeepCopyObj; } public static void CopyObject(object source, object target) { var targetType = target.GetType(); if (targetType == null) { targetType = source.GetType(); } //值型別 if (targetType.IsValueType == true) { target = source; } //引用型別 else { if (source == null) { return; } MemberInfo[] memberCollection = source.GetType().GetMembers(); foreach (MemberInfo member in memberCollection) { if (member.MemberType == MemberTypes.Field) { FieldInfo field = (FieldInfo)member; object fieldValue = field.GetValue(source); if (fieldValue is ICloneable) { field.SetValue(target, (fieldValue as ICloneable).Clone()); } else { field.SetValue(target, CopyObject(fieldValue)); } } else if (member.MemberType == MemberTypes.Property) { PropertyInfo myProperty = (PropertyInfo)member; MethodInfo info = myProperty.GetSetMethod(false); if (info != null) { object propertyValue = myProperty.GetValue(source, null); if (propertyValue is ICloneable) { myProperty.SetValue(target, (propertyValue as ICloneable).Clone(), null); } else { myProperty.SetValue(target, CopyObject(propertyValue), null); } } } } } }
測試:
class User
{
public User(){}
public int id;
public string name;
public User(int id, string name)
{
this.id = id;
this.name = name;
}
}
public class test : MonoBehaviour {
List<User> users;
User user;
// Use this for initialization
void Start () {
users = new List<User>();
user = new User(2,"小花");
}
int b = 5;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
var a = new User();
a = GameTool.CopyObject(user) as User;
a.id = b++;
users.Add(a);
}
}
}
測試結果keyu可以斷點檢視users資料