一:前言

序列化是指把对象转换为字节序列的过程,而反序列化是指把字节序列恢复为对象的过程。序列化最主要的用途就是传递对象和保存对象
在Unity中保存和加载、prefab、scene、Inspector窗口、实例化预制体等都使用了序列化与反序列化


二:可序列化类型

——自定义的具有Serializable特性的非抽象、非泛型类(所有继承UnityEngine.Object的类都具有Serializable特性,如MonoBehaviour)
——自定义的具有Serializable特性的结构体(Unity内置结构体类型都都具有Serializable特性)
——所有基本数据类型,如int、string等(必须为public或具有SerializeField特性且不能为static、const、readonly)
——可序列化类型的数组和列表(如int、string列表),栈、队列、字典等都不能被序列化
——枚举类型


三:Unity中的序列化和反序列化

最直观的就是在Unity中的检视面板可以看到字段就是被成功序列化了的参数,与序列化相关的常用关键字有SerializeField,HideInInspector,NonSerialized,Serializable
——SerializeField : 表示变量可被序列化,SerializeField与private,protected结合使用可以达到让脚本的变量在检视面板里可视化编辑,同时保持它的私有性的目的
——HideInInspector : 将原本显示在检视面板上的序列化值隐藏起来
——NonSerialized :将一个公有变量不序列化并且不显示在检视面板中
——Serializable:用在类的前面,表示该类可被序列化,Serializable不会被派生类所继承,每个类想要被序列化需要单独加Serializable特性


四:通过二进制序列化与反序列化

using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.IO;
using System;
using System.Runtime.Serialization.Formatters.Binary;public class Test : MonoBehaviour
{[MenuItem("Tools/BinarySerialize")]private static void BinarySerialize(){People p = new People();Name name = new Name();name.name1 = "l";name.name2 = "hw";p.name = name;p.age = 26;string path = Application.dataPath + "/Data/PeopleData.bytes";FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);BinaryFormatter binaryFormatter = new BinaryFormatter();binaryFormatter.Serialize(fs, p);fs.Close();AssetDatabase.Refresh();}[MenuItem("Tools/BinaryDeserialize")]private static void BinaryDeserialize(){TextAsset textAsset = AssetDatabase.LoadAssetAtPath<TextAsset>("Assets/Data/PeopleData.bytes");MemoryStream ms = new MemoryStream(textAsset.bytes);BinaryFormatter binaryFormatter = new BinaryFormatter();People p = (People)binaryFormatter.Deserialize(ms);ms.Close();Debug.Log(p.name.name1);Debug.Log(p.name.name2);Debug.Log(p.age);}
}[Serializable]
public class People
{public Name name;public int age;
}[Serializable]
public class Name
{public string name1;public string name2;
}

使用二进制序列化时,每个类都需要Serializable标识
只有通过二进制进行序列化和反序列化时才能调用到OnSerializing、OnSerialized、OnDeserializing、OnDeserialized这四个特性


五:通过Json序列化与反序列化

using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.IO;
using System;public class Test : MonoBehaviour
{[MenuItem("Tools/JsonSerialize")]private static void JsonSerialize(){People p = new People();Name name = new Name();name.name1 = "l";name.name2 = "hw";p.name = name;p.age = 26;string jsonString = JsonUtility.ToJson(p);string path = Application.dataPath + "/Data/PeopleData.json";File.WriteAllText(path, jsonString);AssetDatabase.Refresh();}[MenuItem("Tools/JsonDeserialize")]private static void JsonDeserialize(){string path = Application.dataPath + "/Data/PeopleData.json";StreamReader sr = File.OpenText(path);string jsonString = sr.ReadToEnd();sr.Close();People p = JsonUtility.FromJson<People>(jsonString);Debug.Log(p.name.name1);Debug.Log(p.name.name2);Debug.Log(p.age);}
}public class People
{public Name name;public int age;
}[Serializable]
public class Name
{public string name1;public string name2;
}

使用Json序列化时,第一层类不需要Serializable标识,其他类都需要Serializable标识


六:通过XML序列化与反序列化

using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.IO;
using System.Xml.Serialization;public class Test : MonoBehaviour
{[MenuItem("Tools/XmlSerialize")]private static void XmlSerialize(){People p = new People();Name name = new Name();name.name1 = "l";name.name2 = "hw";p.name = name;p.age = 26;string path = Application.dataPath + "/Data/PeopleData.xml";FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);StreamWriter streamWriter = new StreamWriter(fileStream, System.Text.Encoding.UTF8);XmlSerializer xmlSerializer = new XmlSerializer(p.GetType());xmlSerializer.Serialize(streamWriter, p);streamWriter.Close();fileStream.Close();AssetDatabase.Refresh();}[MenuItem("Tools/XmlDeserialize")]private static void XmlDeserialize(){string path = Application.dataPath + "/Data/PeopleData.xml";FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);XmlSerializer xmlSerializer = new XmlSerializer(typeof(People));People p = (People)xmlSerializer.Deserialize(fileStream);fileStream.Close();Debug.Log(p.name.name1);Debug.Log(p.name.name2);Debug.Log(p.age);}
}public class People
{public Name name;public int age;
}public class Name
{public string name1;public string name2;
}

使用XML序列化时,类不需要Serializable标识,不能序列化私有变量,就算加上NonSerialized标识也无效


七:通过ScriptableObject序列化与反序列化

using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System;public class Test : MonoBehaviour
{[MenuItem("Tools/ScriptableObjectSerialize")]private static void ScriptableObjectSerialize(){string path = "Assets/Data/PeopleData.asset";People p = ScriptableObject.CreateInstance<People>();Name name = new Name();name.name1 = "l";name.name2 = "hw";p.name = name;p.age = 26;AssetDatabase.CreateAsset(p, path);AssetDatabase.Refresh();}[MenuItem("Tools/ScriptableObjectDeserialize")]private static void ScriptableObjectDeserialize(){People p = AssetDatabase.LoadAssetAtPath<People>("Assets/Data/PeopleData.asset");Debug.Log(p.name.name1);Debug.Log(p.name.name2);Debug.Log(p.age);}
}public class People : ScriptableObject
{public Name name;public int age;
}[Serializable]
public class Name
{public string name1;public string name2;
}

使用ScriptableObject序列化时,第一层类不需要Serializable标识,其他类都需要Serializable标识


八:序列化接口—ISerializationCallbackReceiver

——OnBeforeSerialize:序列化前
——OnAfterDeserialize:反序列化后

Unity中Inspector序列化显示Dictionary的方法


九:序列化特性

——OnDeserialized:序列化后
——OnDeserializing:序列化前
——OnSerialized:反序列化后
——OnSerializing:反序列化前
只有通过二进制进行序列化和反序列化时才能调用到OnSerializing、OnSerialized、OnDeserializing、OnDeserialized这四个特性

[Serializable]
public class People
{public Name name;public int age;[OnSerializing]virtual protected void OnSerializing(StreamingContext context){Debug.Log("OnSerializing");}[OnSerialized]virtual protected void OnSerialized(StreamingContext context){Debug.Log("OnSerialized");}[OnDeserializing]virtual protected void OnDeserializing(StreamingContext context){Debug.Log("OnDeserializing");}[OnDeserialized]virtual protected void OnDeserialized(StreamingContext context){Debug.Log("OnDeserialized");}
}

十:Unity中的Prefab

Unity中的Prefab就是游戏对象和组件经过序列化后得到的文件,当你创建一个空物体并制作成预制体后,他会序列化成一个xxx.prefab的文件,这个文件的格式可以是二进制的也可以是文本文件,通过下面的选项可以设置

为什么在运行时修改预制体上的值不会保存?
Unity其实是两层,C++层与Unity控制层,因为Unity是用C++编写的,但是我们自己编写的脚本是C#,就会有一个交互。当我们点击运行按钮时,先是把所有的序列化数据在内部创建,然后把他们存在C++这一层,然后清除Unity控制层这边所有的内存和消息,然后加载我们编写的脚本,最后再把C++层中存储的序列化数据反序列化到Unity控制层中去
在运行时修改字段的值只是更改Unity控制层上的数据,游戏运行过程中会读取这个数据,但不会保存在C++层(Native层),游戏停止后,会再次反序列化Native层中的数据,显示运行前没更改的那个数值

为什么在脚本中定义了变量值,在属性面板上改了之后,使用的是面板上的值而不是脚本中定义的值?
属性面板上的值并不是Unity调用脚本中的C#接口获取的,而是通过对象的反序列化得到的,当修改了属性面板上值后就进行了序列化操作,将值保存到了文件中,面板显示时通过反序列化将文件中的值赋给变量

实例化预制体Instantiate方法的内部过程是首先将参数original所引用的游戏对象序列化,得到序列化流后,再使用反序列化机制将这个序列化流生成一个新的游戏对象,可以说是对象的克隆操作,因此在运行中生成Prefab实例的话可以看到这些实例会带有(Clone)的标记

Unity中的序列化和反序列化相关推荐

  1. fileinputstream自定义类序列化和反序列化_Rest Assured篇:Java中的序列化和反序列化...

    点击上方蓝字设为星标 每天傍晚伴你一起成长! Java 中的序列化和反序列化是一个重要的编程概念.它适用于所有主要的编程语言.在本章中,我们将尝试在Java语言的上下文中理解此概念.在本章的最后,我们 ...

  2. python中常用的序列化模块_Python中的序列化和反序列化

    为什么要序列化 内存中的字典.列表.集合以及各种对象,如何保存到一个文件中. 设计一套协议,按照某种规则,把内存中的数据保存到文件中,文件是一个个字节序列.所以必须把数据额转换为字节序列,输出到文件, ...

  3. 谈谈:.Net中的序列化和反序列化

    序列化和反序列化相信大家都经常听到,也都会用, 然而有些人可能不知道:.net为什么要有这个东西以及.net Frameword如何为我们实现这样的机制, 在这里我也是简单谈谈我对序列化和反序列化的一 ...

  4. .Net 中关于序列化和反序列化Json的方法

    .Net SDK中关于序列化和反序列化Json的方法 项目中遇到和服务端交互时需要传递数据包为json格式的包,所以在服务端和SDK中都需要对json进行解析和组合的操作, 并且对一些复杂结构的jso ...

  5. js序列化与反序列化和C#中json序列化与反序列化

    序列化:将Object转换成JSON字符串 let data = JSON.stringify(obj); // 将JSON对象转化为JSON字符 let data = obj.toJSONStrin ...

  6. OWASP TOP 10(六)反序列化漏洞(序列化和反序列化、漏洞原理、PHP中的序列化和反序列化、魔术方法、Typecho_v1.0中的反序列化漏洞)

    文章目录 反序列化漏洞 一.概述 1. 序列化和反序列化 2. 序列化的目的 二.PHP中的序列化与反序列化 1. 概述 2. 示例序列化与反序列化 3. 反序列化漏洞 - PHP中的魔术方法 - T ...

  7. JAVA中JSON序列化和反序列化

    JAVA中JSON序列化和反序列化 1 FASTJSON的序列化和反序列化 1.1 主函数 1.2 自定义对象 2 GSON序列化和反序列化 2.1 主函数 2.2 自定义对象 总结 不同包序列化和反 ...

  8. php中的序列化与反序列化[喜悦原创]

    php中的序列化与反序列化 1.serialize() <===> unserialize(),这个大家用的最多, 老熟人了 session保存默认用的就是这个. 如果想存储对象,数组数据 ...

  9. K:java中的序列化与反序列化

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?以下内容将围绕这些问题进行展开讨论. Java序列化与反序列化 简单来说Java序列化是指把Java对象转 ...

最新文章

  1. CSDN与易观联合发布《2017-2018中国人工智能产业路线图》
  2. 操作系统习题3—进程的互斥与同步
  3. 专家:大数据等新技术助力信息融合
  4. Delphi 7自带的TeeChart组件
  5. 【华为大咖分享】2.DevCloud on DevCloud 从1月1次到1天10次发布的实践分享(后附PPT下载地址)
  6. 如何做好网站内部优化
  7. 华为nova6升级鸿蒙os,华为公布升级计划:鸿蒙OS系统开始推送,覆盖百款机型
  8. python给定dna等分成两个序列_分析DNA序列中的串联重复序列
  9. 填报true\false和复选框应用及导出打印显示复
  10. 给树莓派安装手柄驱动
  11. 【CentOS8.0开启防火墙放行8081端口】
  12. (二)流(Stream)
  13. 水桶平分 java,JAVA路线
  14. 魅族7.0系统最简单激活Xposed框架的经验
  15. pathon包傻瓜升级
  16. [BJOI2019]勘破神机
  17. 简述计算机无法开机时故障处理方法,主板出问题了怎么办?电脑主板常见问题与故障处理方法...
  18. 用VS2015开发Linux程序详细教程-配置篇
  19. 融资融券黑马选股分析系统主力意图大资金流出流入短线涨停板股票炒股软件
  20. elasticsearch从入门到入门系列(四)---搜索高级使用

热门文章

  1. ZED深度相机的使用--zed-ros-wrapper
  2. Windows10下载更新一直卡在0%解决方法
  3. 首先的亚当和末后的亚当_亚当–循序渐进
  4. html ios滚轮效果控件,深入研究-webkit-overflow-scrolling:touch及ios滚动
  5. 淘宝足迹推荐位是什么
  6. 电脑网络看不到其它计算机,怎么找不到共享电脑,详细教您局域网中共享电脑找不到怎么办...
  7. layui下拉框被弹框遮住问题解决、layui下拉框因弹框显示不全解决方案
  8. pinnacle studio 24旗舰版 新功能以安装教程
  9. 入职总结以及大学生活回顾反省
  10. 全世界有多少程序员?