Unity Class深拷贝问题分析

news/2024/10/18 18:22:02/

Unity Class深拷贝问题分析

  • 前言
  • 常用解决方案
    • 1.手动复制字段
    • 2.使用序列化工具
    • 3.使用Instantiate方法(只能用于MonoBehaviour)
    • 4.重写运算符赋值
    • 5.使用Visual Scripting中提供的拷贝函数(推荐)

深拷贝

前言

在Unity项目中,我们面临一个读取数据表并深拷贝该类的问题。具体情况是这样的:我们需要从数据表中读取人物的数据,但在战斗过程中,人物的数据会不断发生变化。因此,我们需要一个数据类来存储人物的数据,并且希望在不修改原始数据表的情况下,创建一个副本用于战斗。

为了实现这一逻辑,我们采取了以下步骤:首先,我们将Json或Xml格式的数据表反序列化为原始数据类,使用工具进行反序列化操作。然后,我们对原始数据类进行深拷贝,创建一个战斗数据类的副本。通过这种方式,我们既可以使用原始数据表中的数据,又能在战斗过程中对战斗数据类进行修改,而不会影响原始数据表的功能。

这样做的好处是,我们可以在战斗中独立使用战斗数据类,而不会影响原始数据表的完整性。同时,通过深拷贝的方式,我们确保战斗数据类是一个全新的对象,可以独立于原始数据类进行修改,避免了对象引用带来的问题。

常用解决方案

1.手动复制字段

如果类的字段较少且结构简单,可以手动复制每个字段来创建新的对象。这需要逐个复制类的每个字段,并确保复制的是字段的值而不是引用。

public class MyClass
{public int myInt;public string myString;public MyClass DeepCopy(){MyClass newObject = new MyClass();newObject.myInt = myInt;newObject.myString = myString;return newObject;}
}

2.使用序列化工具

使用JsonUtility、MsgPack、Protobuf 等工具库进行序列化和反序列化功能,并能够处理更复杂的类结构。通过将对象序列化为字节流,然后再反序列化为新的对象,可以实现深拷贝。
比如下面这种:

TIP:别用这个,这是我当前项目的,没有对应类用不了

    /// <summary>/// Json文件转实体类/// </summary>/// <typeparam name="T"></typeparam>/// <param name="value"></param>/// <returns></returns>public static List<T> JsonToObject<T>(string value) where T : ConfigJsonBase{List<T> lst = new List<T>();var test = JsonConvert.DeserializeObject<ConfigJsonContainer>(value, settings);test.CopyListToDic();foreach (var item in test.dataMap){T line1 = (T)item.Value;lst.Add(line1);}return lst;}

相当于再次从表中序列化一次获得一个全新的拷贝

3.使用Instantiate方法(只能用于MonoBehaviour)

使用 UnityEngine.Object.Instantiate方法:如果需要复制 Unity 引擎的 GameObjectMonoBehaviour,可以使用 Instantiate方法来创建它们的副本。这个方法会创建一个全新的实例,包括所有的组件和属性,并将它们与原始对象解耦。

public class CopyExample : MonoBehaviour
{public GameObject originalObject;private GameObject copiedObject;public void PerformCopy(){copiedObject = Instantiate(originalObject);// 对复制对象进行进一步操作...}
}

4.重写运算符赋值

下面这个案例是通过重写&运算符实现创建一个新的类并将所有字段赋值。
通过使用&运算符创建新对象时,可以通过将原始对象作为第一个参数传递给运算符,并忽略第二个参数,以触发运算符的重载。新的 newCard对象将具有与原始对象相同的字段值。

这种方法依赖于运算符的重写,并且在使用时需要注意运算符的语义和正确使用方式。另外,由于 & 运算符通常与按位与操作相关,重写它来创建新对象可能会使代码的可读性降低。因此,在实际使用时,建议谨慎选择是否使用这种重写运算符的方法,以确保代码的清晰性和可维护性。

public class CfgCardProperties : ConfigJsonBase
{public string _CardName;public List<string> _CardIconPath;public bool _IsShowCardUnder;public static CfgCardProperties operator &(CfgCardProperties card, CfgCardProperties cfg){CfgCardProperties newCard = new CfgCardProperties();card.ID = cfg.ID;card._CardName = cfg._CardName;card._CardIconPath = cfg._CardIconPath != null ? new List<string>(cfg._CardIconPath) : null;return newCard;}
}

用法是

var cfg = new CfgCardProperties();
cfg &= originalCfgs[i];

5.使用Visual Scripting中提供的拷贝函数(推荐)

Unity Visual Scripting中,CloneViaFakeSerialization节点可以用于实现对象的深拷贝。该节点在 Bolt 或其他 Unity 可视化脚本工具中提供,它通过序列化和反序列化对象来创建其副本。

CloneViaFakeSerialization节点的工作原理如下:

  1. 将要克隆的对象进行序列化,将其转换为字节流。
  2. 将字节流反序列化为一个新的对象。

在上面例子中只需要一行就可以实现类的深拷贝

using Unity.VisualScripting;cfg= originalCfgs[i].CloneViaFakeSerialization();

http://www.ppmy.cn/news/381411.html

相关文章

基于ASP的物流管理系统设计与实现

经济全球化及现代物流业发展的系统化、信息化、仓储运输的现代化和综合化等趋势,对我国物流业的发展提出了全方位的挑战。面对跨国企业不断渗透中国物流市场的严峻形势,我国物流业走高科技之路势在必行。我国国民经济连续多年高速增长,为我国现代物流发展创造了良好的条件。…

漫谈中国数字电视标准的诞生

http://forum.eet-cn.com/BLOG_ARTICLE_8550.HTM 陶显芳 2011-7-8 一、中国数字电视的元年 6月20日&#xff0c;国家标准化管理委员会网站上正式发布了《地面数字电视终端接收机(器)通用规范》(下简称《国家标准》)。《国家标准》从2011年11月1 日正式实施&#xff0c;要求…

了解数字高清电视

[转自&#xff1a;http://vga.zol.com.cn/29/290955.html] [http://baike.baidu.com/view/765885.htm] 720P是美国电影电视工程师协会&#xff08;SMPTE)制定的高等级高清数字电视的格式标准&#xff0c;有效显示格式为&#xff1a;1280720.SMPTE&#xff08;美国电影电视工程…

【代码随想录】刷题Day56刷题Day57

刷题Day56 1.两个字符串的删除操作 583. 两个字符串的删除操作 1.dp数组的含义&#xff1a;dp[i][j]是i-1位置的word1字母与j-1位置的word2字母为结尾时&#xff0c;两个字符串的删除的数目 2.dp数组的操作&#xff1a;首先if(word1[i-1]word2[j-1])&#xff0c;此时两个对应…

好用的Windows数据恢复软件--傲梅恢复之星

​数据恢复软件有什么用&#xff1f; 现在&#xff0c;人们拥有大量的文件需要保留和保护&#xff0c;包括照片、视频、文档、游戏等等。了解数据安全的用户会利用云存储服务和外部设备来存储和备份重要的数据。 但更多的用户并不重视数据备份。这样做是相当危险的&#xf…

STM32F401RCT6基于Arduino框架点灯程序

STM32F401RCT6基于Arduino框架点灯程序 &#x1f4cc;本示例基于《【开源电路】STM32F401RCT6开发板》 ✨经测试&#xff0c;这次跑示例程序没有遇到像STM32F103VET6那样的串口乱码的bug&#xff0c;串口打印正常。 &#x1f4d3;串口指定方式 &#x1f4cb;翻阅固件源码可…

STM32入门:STM32F401CDU6库函数工程文件搭建

STM32F401CDU6库函数工程文件搭建 根据下图的结构进行复制粘贴操作&#xff0c;代码部分在本文末有贴出来&#xff0c;STM32F4xx-DSP-StdPeriph-Lib-V1.8.0文件下载&#xff08;使用part1即可&#xff09; 完成以上操作后&#xff0c;将Output与Listing生成的文件置于OBJ文件…

STM32F401超声波proteus仿真

STM32F401超声波仿真 文章目录 前言一、仿真效果二、相关代码1.串口2.LCD3.SFR04 总结 前言 仿真功能描述&#xff1a; 使用串口和LCD屏输出SFR04距离数据 proteus版本8.11 安装包链接&#xff1a;https://pan.baidu.com/s/1yhNKLl1lGSU9KU0tTuAxcg?pwddxe8 提取码&#xff…