Unity中的序列化数据丢失

2023-11-10

Unity中的序列化数据丢失

问题描述

        近期在项目制作中,需要运用Asset进行数据结构的实例化存储和使用,在制作编辑器的过程中发现一个十分尴尬的问题,在某些情况下会发生代码修改后通过编辑器配置的某些数据会丢失,我把这种问题叫做“序列化数据丢失”(因为我也不知道怎么称呼它)。

通过一个简单的示例可以体现出该问题:

public string[][] twoString = new string[1][] ;

以上为一个二维数组的结构体,对其进行赋值后保存成Asset文件。在不改动源代码的情况下,配置进入的数据可以正常的读取并且不会丢失,但当我们对任意文件进行代码修改并保存后(工程对代码进行重新编译)。再次读取该Asset文件会发现数据全部丢失。

问题测试

我对该问题进行了各种可能性的测试寻找会出现序列化数据冲刷现象的情况,如下数据测试用例:

// 失败的方式

    public TDictionary<string, string> testT=new TDictionary<string, string>();

    // 正确的方式

    public TestDictionary testDictionary = new TestDictionary();

    // 正确的方式

    public List<string> testString = new List<string>();

    // 失败的方式

    public string[][] twoString = new string[1][] ;

    // 正确的方式

    public DepthDictionary depth = new DepthDictionary();

    // 失败的方式

    public DepthErrDictionary depthErr = new DepthErrDictionary();

        其中TDictionary使用的是第三方编写的继承自IDictionary实现的字典数据结构,该第三方框架地址: https://github.com/neuecc/SerializableDictionary

Depth相关数据结构:

    [Serializable]

    public class PathItem

    {

        public PathItem(string path)

        {

            this.path = path;

        }

        // 路径

        public string path;

    }

    [Serializable]

    public class PathsList

    {

        public PathsList(string path)

        {

            psList.Add(new PathItem(path));

        }

        public List<PathItem> psList = new List<PathItem>();

    }

    [Serializable]

    public class DepthDictionary : AssetDictionary

    {

        public PathsList[] list;

        public DepthDictionary()

        {

            list = new PathsList[MAX];

        }

        protected override T[] GetValues<T>()

        {

            return list as T[];

        }

        protected override void SetValues<T>(T[] values)

        {

            list = values as PathsList[];

        }

    }

    [Serializable]

    public class DepthErrDictionary : AssetDictionary

    {

        public List<PathItem>[] list;

        public DepthErrDictionary()

        {

            list = new List<PathItem>[MAX];

        }

        protected override T[] GetValues<T>()

        {

            return list as T[];

        }

        protected override void SetValues<T>(T[] values)

        {

            list = values as List<PathItem>[];

        }

}

问题解决

通过测试用例大体总结出来的会导致数据冲刷的现象出现在如下几点:

1. 泛型类的使用,但是注意如果直接使用List<T>是不会发生问题,注:T需满足当前所述几点条件。

2. 嵌套的数组结构,无论是[][]还是List<T>[]都会产生问题。

3. 不可序列化的数据结构(如Dictionary)。

所以遵循以上几点去实现数据结构将规避该问题的发生,其中一个重要的是Dictionary的支持,以及多维数组的支持。

多为数组的方案在上述测试DepthDictionary中应用并演示,使用嵌套对象的方式解决,结果如图:


提供一份简单的Dictionary实现例子,本例采用哈希冲突的线性探测方式实现,以供参考。

public abstract class AssetDictionary

    {

        protected string[] keys;

        // 线性探索表的块大小

        protected int M = 16;

        // 数据块幂数

        protected const int N = 8;

        protected int ADDI = 0;

        // 2^N

        protected int MAX;

        protected int KEYS_COUNT = 0;

        protected int lenght = 0;

        public int Count {

            get { return lenght; }

        }

        protected abstract T[] GetValues<T>();

        protected abstract void SetValues<T>(T[] values);

        public AssetDictionary()

        {

            MAX = (int)Math.Pow(2, N);

            keys = new string[MAX];

        }

        public void Add<T>(string key,T value)

        {

            int index = key.GetHashCode() % MAX;

            // **数据

            for (int i = 0; i < M; i++)

            {

                if (index == MAX)

                    index = 0;

                if (keys[index] != null && keys[index] != key)

                    continue;

                keys[index] = key;

                GetValues<T>()[index] = value;

                lenght++;

                return;

            }

            // 重构数据块大小

            resetBlock<T>(null,null);

            Add<T>(key, value);

        }

        public bool Remove<T>(string key)

        {

            int index = key.GetHashCode() % MAX;

            // **数据

            for (int i = 0; i < M; i++)

            {

                if (index == MAX)

                    index = 0;

                if (keys[index] == key)

                {

                    keys[index] = null;

                    GetValues<T>()[index] = default(T);

                    lenght--;

                    return true;

                }

            }

            return false;

        }

        public T GetValue<T>(string key)

        {

            int index = key.GetHashCode() % MAX;

            if(keys[index] == null)

                return default(T);

            // **数据

            for (int i = 0; i < M; i++)

            {

                if (index == MAX)

                    index = 0;

                if (keys[index] == key)

                    return GetValues<T>()[index];

            }

            return default(T);

        }

        protected void resetBlock<T>(string[] copyKeys,T[] copyValues)

        {

            // 增加新的区块

            ADDI += 1;

            MAX = (int)Math.Pow(2, N + ADDI);

            M = (int)Math.Pow(2, 4 + ADDI);

            // 原始数据空间

            if(copyKeys == null)

                copyKeys = keys;

            if(copyValues == null)

                copyValues = GetValues<T>();

            // 覆盖重置空间

            keys = new string[MAX];

            SetValues<T>(new T[MAX]);

            // 重构空间,根据目前持有的key进行

            for(int i = 0; i < copyKeys.Length; i++)

            {

                if(copyKeys[i] != null)

                {

                    if(AddBlockValue<T>(copyKeys[i], copyValues[i]) == false)

                    {

                        // 列表超出最大范围

                        resetBlock<T>(copyKeys,copyValues);

                        return;

                    }

                }

            }

        }

        protected bool AddBlockValue<T>(string key,T value)

        {

            int index = key.GetHashCode() % MAX;

            // **数据

            for (int i = 0; i < M; i++)

            {

                if (index == MAX)

                    index = 0;

                if (keys[index] != null)

                    continue;

                keys[index] = key;

                GetValues<T>()[index] = value;

                return true;

            }

            return false;

        }

}

使用中需要继承AssetDictionary并实现如上边提到的数据结构中Depth相关的代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity中的序列化数据丢失 的相关文章

  • java混编

    java里面总共有八种基本数据类型 其分别为 byte short char int long float double Boolean 其他都是引用数据类型 而引用数据类型是以对象的形式存在 基本数据类型都可以直接进行运算 没必要先换算成
  • [python] 时间序列分析之ARIMA

    1 时间序列与时间序列分析 在生产和科学研究中 对某一个或者一组变量 x t x t 进行观察测量 将在一系列时刻 t1 t2 tn t 1 t 2 cdots t n 所得到的离散数字组成的序列集合 称之为时间序列 时间序列分析是根据系统
  • 自动记录数据录入时间不懂得VBA的朋友可以看看

    在日常工作中 经常会遇到需要实时记录数据录入的时间问题 有朋友会说了 用快捷键啊 按Ctrl 分号 可以返回当前的系统日期 按Ctrl Shift 分号 可以返回当前的系统时间 但是如果需要同时返回日期和时间又该怎么处理呢 对于懂得VBA的
  • 【机器学习】Tensorflow概率编程:线性混合模型

    线性模型是我们最常见到的 最理想的数学模型 基本的线性模型是数据科学入门的基本案例 然而现实生活中的线性问题 很大几率不适用于基本的线性模型 需要使用线性混合模型来描述 Tensorflow edward提供对这类问题的解决方案 大部分数据
  • Qt线程之间通过signal和slot传递数据

    Qt线程之间通过signal和slot传递数据 这种方法主要是为了设置自己定义的数据类型 在不同的线程之间进行通信 如果自己定义的数据类型未经处理之间传递会报如下错误 QObject connect Cannot queue argumen
  • 数据属性类型

    数据集由数据对象组成 一个数据对象代表一个实体 数据对象又称样本 实例 数据点或对象 属性 attribute 是一个数据字段 表示数据对象的一个特征 属性向量 或特征向量 是用来描述一个给定对象的一组属性 属性有不同类型 标称属性 nom
  • Oracle 错误 maximum number of processes(150) exceeded 解决办法

    只保留以上服务 关掉其他没用的服务即可
  • 基于ArcGIS的nc(NETCDF)转tif格式

    软件版本 ArcMap10 4 1 nc NETCDF 是一组独立于机器的软件库支持创建 访问和共享面向阵列的数据格式科学数据 它也是共享科学数据的社区标准 摘自Unidata官网 被广泛应用于大气 海洋 水文等领域 是我们日常学习和工作中
  • 如何在数据验证单元格区域禁用粘贴

    为了确保数据准确性 在A列设置了数据验证 可以输入值的列表如下图所示 但是如果用户使用复制 粘贴 仍然可以输入其他值 如下图所示 使用如下事件可以实现禁止粘贴 Private Sub Worksheet Change ByVal Targe
  • 你的数据隐私值多少钱?也许已有答案了

    全文共6032字 预计学习时长12分钟 图片来源 Timo Lenzen 对于一些大型科技公司来说 这一年侵犯用户隐私付出的代价变高了 未来还会更高吗 今年7月 脸书在受到有关泄露数亿用户数据隐私的指控后 同意缴纳50亿美元的罚金 同一周内
  • Matlab深度学习笔记——深度学习工具箱说明

    本文是Rasmus Berg Palm发布在Github上的Deep learning toolbox的说明文件 作者对这个工具箱进行了详细的介绍 原文链接 https github com rasmusbergpalm DeepLearn
  • 统计学习方法学习笔记(一)————统计学习方法概论

    1 统计学习 1 统计学习概念 统计学习 statistical learning 是关于计算机基于数据构建概率统计模型并运用模型对数据进行预测与分析的一门学科 统计学习也称为统计机器学习 statistical machine learn
  • 数据倾斜

    数据倾斜发生时的现象 1 绝大多数task执行得都非常快 但个别task执行的极慢 2 原本能正常执行的Spark作业 某天突然爆出OOM 内存溢出 异常 观察异常栈 是我们写的业务代码造成的 数据倾斜发生的原理 在进行shuffle的时候
  • 数据分析和挖掘常用方法

    数据分析和挖掘常用方法 介绍 聚类分析 回归分析 分类分析 以及其他常用分析手段 不同方法的内在业务联系 聚类分析 用户由哪些群体组成 这些群体有哪些明显特征 回归分析 未来销售趋势预测 营销投入如何影响销售 分类分析 如何筛选出更值得营销
  • 数据链路层的有那三个基本问题?为什么都必须加以解决?

    数据链路层的有那三个基本问题 为什么都必须加以解决 数据链路层的三个基本问题 封装成帧 透明传输 差错检测 封装成帧就是在一段数据前后分别添加首部和尾部 接收端以便从收到的比特流中识别帧的开始与结束 帧定界是分组交换的必然要求 透明传输避免
  • 2013-2020年全国31省数字经济数据集

    1 时间 2013 2020年 2 来源 整理自国家统计J和统计NJ 3 指标包括 信息化基础 光缆线路长度 公里 移动电话基站 万个 信息传输 软件和信息技术服务业城镇单位就业人员 万人 年末常住人口 万人 城镇单位就业人员 万人 光缆密
  • kafka权威指南中文版之三

    第三章kafka producer 向kafka写入消息 无论你将kafka作为一个消息队列 或者消息总线 还是一个数据存储平台 你都要通过生产者producer向kafka写入数据 通过消费者consumer读取kafka的数据 例如 一
  • 微信小程序API——向服务器发送请求

    在微信小程序中 我们可以通过微信的API与服务器进行数据传递 接下来我会详细介绍一下wx request的用法 首先给出前端代码 我们定义一个按钮 绑定点击事件 用于给服务器发送请求 当服务器返回数据后 通过wx for循环出数组中的数据
  • 中国省份城市0-N编号

    1 中国省份0 N编号 上海 1 云南 2 内蒙古 3 北京 4 台湾 5 吉林 6 四川 7 天津 8 宁夏 9 安徽 10 山东 11 山西 12 广东 13 广西 14 新疆 15 江苏 16 江西 17 河北 18 河南 19 浙江
  • MES11大标准模块(ISA95)

    1 资源分配及状态管理 ResourceAllocationandStatus 该功能管理机床 工具 人员物料 其它设备以及其它生产实体 满足生产计划的要求对其所作的预定和调度 用以保证生产的正常进行 提供资源使用情况的历史记录和实时状态信

随机推荐

  • php验证用户账号密码正确,php-检查用户名和密码是否正确

    因为我的代码是正确的 所以我总是得到回显 Username Passwordcorrect 用户名 密码是否匹配 我的问题是 我在下面的代码中为PHP总是回显 用户名 密码错误 而做错了什么 require privstuff dbinfo
  • jupyter notebook使用基础及其快捷键,包括对文档操作、cell操作、快捷键、markdown

    目录 Jupyter Notebook介绍 使用原因 基本操作 新建notebook文档 对文档的操作 cell操作 什么是cell Jupyter支持两种模式 鼠标操作 Jupyter快捷键操作 markdown演示 手动建导航 Jupy
  • 网络编程 - Java SSLSocketFactory 创建方式

    SSL TLS 认证需要服务端提供 KeyStore jks TrustStore jks 实现方式 优缺点 服务端提供 CA Client CRT Client Key 文件 缺点 服务端提供原始签名 不安全不建议采用 服务端提供 Key
  • linux $0命令,Linux:awk命令详解

    简单使用 awk 对于文件中一行行的独处来执行操作 awk F print 1 4 使用 来分割这一行 把这一行的第一第四个域打印出来 AWK命令介绍 awk语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息 awk抽取信息后 才
  • 2023最新pycharm详细安装教程,小白必看

    一 python官网 Python官网主要有python的About 简介 Downloads 下载 Documentation 文档 Community 团体 Success Stories 成功案例 News 新闻 Events 事件动
  • 贪吃蛇智能版(专家)

    在高级版本的基础之上 主要针对以下问题进行了处理 当长度逐渐变成 超过100之后 随机wander 追尾有比较大的随机性 弄不好就把自己围死了 这个时候已经不能再看到实物马上就去吃了 在吃之前必须先调整好自身的状态 等到认为调整的差不多的时
  • 如何在sqlserver建立新用户并关联相应的数据库

    我们经常需要在数据库上建立有权限的用户 该用户只能去操作某个特定的数据库 比如该用户只能去读 去写等等 那么我们应该怎么在sqlserver上设置呢 下面的步骤有点长 只要一步一步跟着设置就行 方法 步骤 如果你没有开通sqlserver身
  • GoWeb开发-3.JWT

    1 导入依赖库 go get u github com dgrijalva jwt go 2 生成token import fmt github com gin gonic gin jwt github com dgrijalva jwt
  • 将树莓派上的文件发送到服务器,怎样将树莓派变成网络文件系统版本4服务器...

    简介 网络文件系统 NFS 可以同时在版本2 3 4中运行 NFS版本4 NFSv4 在NFSv2和NFSv3 我最喜欢的改进是 NFSv4使配置防火墙变得简单 因为NFSv4仅使用一个端口 默认为2049 而NFSv2和NFSv3使用4个
  • 搭建 llvm 学习环境

    1 下载llvm git clone https github com llvm llvm project git 因为国内网络的原因 clone的时候没有反应 可以多此 Ctrl C 重新 clone 2 下载安装cmake 注意 下载的
  • 毕业设计-基于学习元的双螺旋深度学习模型

    目录 前言 课题背景和意义 实现技术思路 一 基于学习元的深度学习支撑系统 二 双螺旋深度学习模型 三 深度学习的开放课程设计实践 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备
  • 网页打开摄像头_听说,考试的时候你打不开摄像头?

    近期真没什么可写的 赶在考试之前就来说一说雨课堂打不开摄像头如何解决吧 先推荐一个检测浏览器摄像头权限的网址 https assistant ceping com qrcode type 1 lng zh 如果在这个网址下摄像头一切正常 雨
  • uplift model增益模型相关术语概念名词汇总

    因果推断 增益模型综述 http proceedings mlr press v67 gutierrez17a gutierrez17a pdf 名词 缩写 英文全称 名词解释 备注 treatment 干预 实验组 control 不干预
  • vscode代码发送至微信开发者工具无法识别mqtt服务器地址(无论正确服务器地址还是错误地址,均不报错也不连接)

    调试器可以正常显示报错 并且小程序界面一也可以更新UI 但是唯独不更新服务器部分的错误 未搜索到相似问题 个人尝试出了一个解决办法 解决了我个人的这个问题 不一定普适 供参考 卸载mqtt npm uninstall mqtt 安装2 18
  • gradle:Connection timed out 问题解决

    gradle Connection timed out 问题解决 gradle Connection timed out 问题解决 先来重现一下问题 公司技术选型使用了gradle作为构建工具 问题重现 使用的系统是windows10 准备
  • fgets函数使用

    一 作用 fgets函数用于从指定的文件流中读取一行字符串 并将其存储到指定的字符数组中 它可以读取包括空格在内的所有字符 直到遇到换行符或文件结束符为止 fgets函数还可以指定最大读取的字符数 以防止缓冲区溢出 二 使用方法 fgets
  • HJ17 坐标移动

    Powered by NEFU AB IN Link 文章目录 HJ17 坐标移动 题意 思路 代码 HJ17 坐标移动 题意 开发一个坐标计算工具 A表示向左移动 D表示向右移动 W表示向上移动 S表示向下移动 从 0 0 点开始移动 从
  • 26、【链表】相交链表(C++版本)

    题目描述 题目分析 目标是找到两个链表若相交时的公共结点 那么便需要分析公共结点所具有的特性 假设链表A和链表B具有公共结点 那么在公共结点处之后 两个链表具有相同长度和数值的结点 而在公共结点之前 两个链表的所具有的结点个数并不一定相等
  • 网络请求【小程序】

    一 get 二 post 1 获取相应数据 Page 页面的初始数据 data inptValue isArr 生命周期函数 监听页面加载 onLoad options onSubmit console log this data inpt
  • Unity中的序列化数据丢失

    问题描述 近期在项目制作中 需要运用Asset进行数据结构的实例化存储和使用 在制作编辑器的过程中发现一个十分尴尬的问题 在某些情况下会发生代码修改后通过编辑器配置的某些数据会丢失 我把这种问题叫做 序列化数据丢失 因为我也不知道怎么称呼它