Unity C#序列化和反序列化(.bin .xml .json)
文章目录
一、序列化的概念
序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。其目的是以某种存储形式使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方。
简单来说就是将对象保存到文件中。如Unity的场景文件和预制体默认就是以二进制的文件保存在工程目录下。
Unity序列化
在Unity中,在检视面板中可以看到的,就是被成功序列化了的参数。与序列化相关的常用的关键字有SerializeField,HideInInspector,NonSerialized,Serializable并可以组合使用。
SerializeField : 表示变量可被序列化。众所周知,公有变量可以在检视面板中看到并编辑,而私有和保护变量不行。SerializeField与private,protected结合使用可以达到让脚本的变量在检视面板里可视化编辑,同时保持它的私有性的目的。
HideInInspector : 将原本显示在检视面板上的序列化值隐藏起来。
NonSerialized :通过此方法可以将一个公有变量不序列化并且不显示在检视面板中。
Serializable:用在类的前面,表示该类可被序列化。
下面用一段代码来举例说明:
public class Test :Monobehavior
{
public int a; //序列化,显示
private int b; //不序列化,不显示
[SerializeField ] int c; //序列化,显示
[HideInInspector] public int d; //序列化,不显示
[NonSerialized ] public int e; //不序列化,不显示
public Test2 test2; //序列化,显示(可序列化的部分)
}
[Serializable ]
public class Test2
{
public int aa;
private int bb;
}
此外,Unity还有SerializedObject 和 SerializedProperty,常用于编辑器模式下的工具或导入器中,修改资源或者Prefab的属性。具体可参考官方文档:https://docs.unity3d.com/ScriptReference/SerializedObject.html
注意: 并非所有的公有变量都是可以被序列化的。其中const,static是静态的,属于类而非对象,无法序列化。链表和字典在内存中的存储是不连续的,也无法序列化。
二、C#常用的序列化
首先我们先定义一个可被序列化的类DemoClass
[Serializable]
public class DemoClass
{
public int _id;
public string _myName;
public DemoClass(int id, string myName)
{
_id = id;
_myName = myName;
}
public DemoClass()
{
}
public void Output()
{
Debug.LogError(_id);
Debug.LogError(_myName);
}
}
它包含两个公有变量id和name,一个含参的构造函数和一个默认构造函数(二进制不需要,XML必须), 一个用于显示的输出函数。
1.二进制序列化(Binary Formatter)
序列化:新建或打开一个二进制文件,通过二进制格式器将对象demo写入该文件中。
void WriteTest()
{
DemoClass demo = new DemoClass (100, "RCD");
FileStream fs = new FileStream ("demo.bin", FileMode.OpenOrCreate);
BinaryFormatter bf = new BinaryFormatter ();
bf.Serialize (fs, demo);
fs.Close ();
Debug.LogError ("write done");
}
反序列化:打开待反序列化的二进制文件,通过二进制格式器将文件解析成对象demo,并输出到控制台。
void ReadTest()
{
FileStream fs = new FileStream("demo.bin", FileMode.Open);
BinaryFormatter bf = new BinaryFormatter();
DemoClass demo = bf.Deserialize(fs) as DemoClass;
fs.Close();
demo.Output();
}
2.XML的序列化(XML Serializer)
序列化与反序列化与二进制方法十分类似,但必须包含一个默认构造函数
void WriteTest()
{
DemoClass demo = new DemoClass(100, "RCD");
FileStream fs = new FileStream("demo.xml", FileMode.OpenOrCreate);
XmlSerializer xml = new XmlSerializer(typeof(DemoClass));
xml.Serialize(fs, demo);
fs.Close();
Debug.LogError("write done");
}
void ReadTest()
{
FileStream fs = new FileStream("demo.xml", FileMode.Open);
XmlSerializer bf = new XmlSerializer(typeof(DemoClass));
DemoClass demo = bf.Deserialize(fs) as DemoClass;
fs.Close();
demo.Output();
}
3.Json的序列化(Newtonsoft.Json)
Json的序列化UnityPackge里有很多现成的插件"com.unity.modules.jsonserialize": “1.0.0”,,这是Unity官方推荐的Newtonsoft.Json,相对功能要更加的强大。
using Newtonsoft.Json;
我们可以直接把DemoClass类转成Json string:
DemoClass demo = new DemoClass(100, "RCD");
string JsonString= JsonConvert.SerializeObject(demo);
同理 也可以将一个Json文本转成对应的C#对象:
DemoClass demo=JsonConvert.DeserializeObject<DemoClass>(JsonString);
demo.Output();
注意: 使用Newtonsoft不需要再在类或者字段前加[Serializable],Newtonsoft理论上可以转化所有C#对象,包括字典
归纳一下Newtonsoft就是:
JObject 用于操作JSON对象(值得注意的是用完JObject一定要将其置为JObject=null 否这会引起内存增长)
JArray 用语操作JSON数组
JValue 表示数组中的值
JProperty 表示对象中的属性,以"key/value"形式
JToken 用于存放Linq to JSON查询后的结果
更多的内容可以查看官方文档:https://www.newtonsoft.com/json/help/html/SerializeWithJsonConverters.htm
4.Unity类的Json序列化(Unity提供)
使用 JsonUtility 类可在 Unity 对象与 JSON 格式之间来回转换。例如,可以使用 JSON 序列化与 Web 服务进行交互,或者轻松地将数据压缩和解压缩为基于文本的格式。
使用 JsonUtility.ToJson 方法将其序列化(转换)为 JSON 格式:
string json = JsonUtility.ToJson(myObject);
将 JSON 转换回对象,使用 JsonUtility.FromJson:
yObject = JsonUtility.FromJson<MyClass>(json);
用 JSON 覆盖对象:
JsonUtility.FromJsonOverwrite(json, myObject);
关于JsonUtility更多可以参考官方文档
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!