Unity Class深拷贝问题分析

news2024/12/23 17:41:14

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.coloradmin.cn/o/645287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3--Gradle入门 - 创建普通的Java工程

3--Gradle入门 - 创建普通的Java工程 前言 前面我们以及尝试过使用 Gradle 创建项目&#xff0c;下面我们使用 Idea 来创建普通的Java工程 创建普通的Java工程 1. 创建 Gradle 管理依赖的项目 语言设置 Java 依赖设置 Gradle DSL 使用 Groovy 2. 设置项目使用本地的 gradle …

B树和B+树索引

B树索引 磁盘IO读数据到内存 malloc/new 向 kernel申请4B空间&#xff0c;实际系统可能给2个页面空间即8KB&#xff0c;剩下8KB-4B空间由 lib.so 或libc.so 的 ptmalloc 或tcmalloc管理 。这样就不需要每次去kernel申请内存 磁盘IO同理&#xff0c;我们读一部分数据会把一整…

2023年6月DAMA-CDGP数据治理专家认证,这家口碑好

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

研一,有点迷茫。

作者&#xff1a;阿秀 校招八股文学习网站&#xff1a;https://interviewguide.cn 这是阿秀的第「277」篇原创 小伙伴们大家好&#xff0c;我是阿秀。 最近回答了不少大一大二研一在读的学习圈中学弟学妹的咨询问题&#xff0c;基本都是计算机学习、进度、疑惑等等相关的问题&a…

chatgpt赋能python:Python怎么批量注释

Python怎么批量注释 Python是一种高级编程语言&#xff0c;广泛应用于数据科学、人工智能、Web开发等领域。在编写Python代码时&#xff0c;注释是非常重要的一部分。注释可以帮助程序员更好地理解代码&#xff0c;便于代码的维护和修改。但有时候&#xff0c;我们需要批量注释…

华为OD机试真题 JavaScript 实现【火星文计算】【2022Q2 100分】,附详细解题思路

一、题目描述 已知火星人使用的运算符为#、$&#xff0c;其与地球人的等价公式如下&#xff1a; x#y 2*x3*y4 x$y 3*xy2 其中x、y是无符号整数&#xff1b;地球人公式按C语言规则计算&#xff1b;火星人公式中&#xff0c;$的优先级高于#&#xff0c;相同的运算符&#x…

YOLOv5/7 更换 DIoU-NMS

文章目录 NMS原理介绍DIoU-NMS效果展示NMS 耗时对比YOLOv5 更换方式YOLOv7 更换方式NMS原理介绍 在执行目标检测任务时,算法可能对同一目标有多次检测。NMS 是一种让你确保算法只对每个对象得到一个检测框的方法。 在正式使用NMS之前,通常会有一个候选框预清理的工作(简单引…

二、微机保护的结构框图原理

在实际应用中&#xff0c;微机保护装置分为单CPU和多CPU的结构方式。在中、低压变电所中多数简单的保护装置采用单CPU结构&#xff0c;而在高压及超高压变电所中复杂保护装置广泛采用多CPU的结构方式。 &#xff08;一&#xff09;单 CPU的结构原理 单CPU的微机保护装置是指整套…

5.3.1 因特网的路由协议(一)

5.3.1 因特网的路由协议&#xff08;一&#xff09; 我们知道因特网在现实生活中的应用非常广泛&#xff0c;我们可以进行网络聊天、查询资料&#xff0c;购物等&#xff0c;他给我们的现实生活带来了极大地方便&#xff0c;我们已经知道互联网是由一个个经过路由器连接的网络…

Java设计模式(八)— 单例模式3

系列文章目录 单例模式之静态内部类 单例模式之枚举方式 单例模式之JDK源码分析 文章目录 系列文章目录前言一、单例—静态内部类1.静态内部类案例2.静态内部类优缺点 二、单例—枚举方式1.枚举方式案例2.枚举方式优缺点 三、单例—JDK源码分析1.JDK源码分析 四、单例模式注意…

Java同步容器和并发容器

同步容器 在 Java 中&#xff0c;同步容器主要包括 2 类&#xff1a; Vector、Stack、HashTable Vector 实现了 List 接口&#xff0c;Vector 实际上就是一个数组&#xff0c;和 ArrayList 类似&#xff0c;但是 Vector 中的方法都是 synchronized 方法&#xff0c;即进行了同…

大型企业的知识库是什么结构的?真的有用吗?

大型企业的知识库是指建立在企业内部的一个包含各种知识和信息的系统&#xff0c;它可以帮助企业更好地管理和利用企业内部的知识资源&#xff0c;提高企业的创新能力和竞争力。 知识库的结构和内容包括以下几个方面 一、知识分类和标签化 在建立知识库之前&#xff0c;企业…

哪款佩戴舒适的蓝牙耳机好?公认佩戴舒适度高的蓝牙耳机推荐

现如今&#xff0c;蓝牙耳机越多人使用&#xff0c;不同于有线耳机&#xff0c;蓝牙耳机更为方便&#xff0c;没有线束的困扰&#xff0c;走到哪也不用带上手机一起&#xff0c;特别便利。然而&#xff0c;随着蓝牙耳机市场的扩大&#xff0c;各种类型各种样式的耳机五花八门&a…

骨传导蓝牙耳机怎么用,分享几款不错的骨传导耳机

骨传导技术是利用振动将声音转化为不同频率的机械振动&#xff0c;通过人的颅骨、骨迷路、内耳淋巴液传递、螺旋器、听神经、听觉中枢来传递声波。相比传统耳机&#xff0c;它在运动时使用&#xff0c;不会损伤到我们的听力。它不需要入耳佩戴&#xff0c;佩戴更舒适健康。 骨传…

悄悄告诉你有什么免费的ai绘画工具

是不是每次看到一幅美丽的画作&#xff0c;你都会心生羡慕&#xff0c;想要自己也能创造出那样的艺术品&#xff1f;别担心&#xff0c;现在有了ai绘画工具&#xff0c;你也可以轻松成为一位小小画家&#xff01;这些神奇的工具不仅能够帮助你发挥创造力&#xff0c;还能让你玩…

SQL Server 中count方法和case when语句配合使用中的问题

概要 我们在使用SQL Server生成报表统计数据的时候&#xff0c;经常使用sum&#xff0c;count等聚合函数&#xff0c;有时候还会配合case when语句一边执行过滤操作&#xff0c;一边进行聚合。 本文介绍一个在使用中的常见的错误和解决方法。 设计和实现 下面是一张订单记录…

【链表复习】C++ 链表复习及题目解析 (2)

目录 牛客 CM11 链表分割 牛客 OR36 之链表的回文结构 Leetcode 160. 相交链表 LeetCode 141. 环形链表 LeetCode 138. 复制带随机指针的链表 本文继续延续前文&#xff0c;为大家带来几道经典的链表中等难度的题目。 牛客 CM11 链表分割 现有一链表的头指针 ListNode* p…

探索iOS之Metal标准库

Metal标准库包括&#xff1a;通用函数、整型函数、关系函数、数学函数、矩阵运算、SIMD运算、几何函数、纹理函数等。接下来让我们走进Metal标准库的世界。 1、通用函数 通用函数在<metal_common>头文件中&#xff0c;T为scalar或vector的浮点类型。如下表所示&#xf…

公司最大的内卷,是OKR驱动

作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 去年5月&#xff0c;以善用OKR独步江湖的Google公司宣布将对 Google 员工的绩效管理方式进行改革——Google 开始使用一种名为 GRAD 的新绩效评估流程。据了解&#xff0c;这一调整主要是基于员工对谷…

集权设施管理-AD域安全策略(二)

活动目录&#xff08;AD&#xff09;凭借其独特管理优势&#xff0c;从众多企业管理服务中脱颖而出&#xff0c;成为内网管理中的佼佼者。采用活动目录来管理的内网&#xff0c;称为AD域。 了解AD域&#xff0c;有助于企业员工更好地与其它部门协作&#xff0c;同时提高安全意…