【游戏技术群】959392658  【游戏出海群】12067810
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2395

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 2995|回复: 32

[士郎] Unity与C#的序列化与反序列化

[复制链接]  [移动端链接]
排名
1
昨日变化

7201

主题

7731

帖子

2万

积分

Rank: 16

UID
1231
好友
185
蛮牛币
11748
威望
30
注册时间
2013-7-29
在线时间
3692 小时
最后登录
2019-1-18

社区QQ达人活力之星原创精华达人突出贡献奖财富之证游戏蛮牛QQ群会员蛮牛妹VIP

发表于 2018-12-14 15:00:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
序列化操作在我们的开发中使用的十分普遍,本文记录了公司最近分享会上关于这部分的讲解,希望能帮助大家对序列化有更系统的了解。

概念
序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。其目的是以某种存储形式使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方。

简单来说就是将对象保存到文件中。如Unity的场景文件和预制体默认就是以二进制的文件保存在工程目录下。
Unity序列化
在Unity中,在检视面板中可以看到的,就是被成功序列化了的参数。与序列化相关的常用的关键字有SerializeField,HideInInspector,NonSerialized,Serializable并可以组合使用。

  • SerializeField : 表示变量可被序列化。众所周知,公有变量可以在检视面板中看到并编辑,而私有和保护变量不行。SerializeField与private,protected结合使用可以达到让脚本的变量在检视面板里可视化编辑,同时保持它的私有性的目的。
  • HideInInspector : 将原本显示在检视面板上的序列化值隐藏起来。
  • NonSerialized :通过此方法可以将一个公有变量不序列化并且不显示在检视面板中。
  • Serializable:用在类的前面,表示该类可被序列化。

下面用一段代码来举例说明:
[AppleScript] 纯文本查看 复制代码
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;
}

我们新建一个Test脚本来验证一下,输入上述代码后观察检视面板:
1.png
然后将挂在脚本的预制体用Sublime打开观察序列化部分:
2.png
耶,成功了!
此外,Unity还有类SerializedObject,常用于编辑器模式下的工具或导入器中,修改资源或者Prefab的属性。具体可参考官方文档:
注意:并非所有的公有变量都是可以被序列化的。其中const,static是静态的,属于类而非对象,无法序列化。链表和字典在内存中的存储是不连续的,也无法序列化。其中const,static,readonly的区别可参考文章:

C#序列化
简单介绍两种常用的C#序列化操作(二进制方法和XML方法)
首先我们先定义一个可被序列化的类DemoClass
[AppleScript] 纯文本查看 复制代码
[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必须), 一个用于显示的输出函数。

二进制方法(Binary Formatter)
序列化:新建或打开一个二进制文件,通过二进制格式器将对象demo写入该文件中。
[AppleScript] 纯文本查看 复制代码
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");
}
3.png
反序列化:打开待反序列化的二进制文件,通过二进制格式器将文件解析成对象demo,并输出到控制台。
[AppleScript] 纯文本查看 复制代码
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();
}


4.png
耶,成功了!
注意:二进制方法可以序列化私有变量,不能序列化被[NonSerialized ]修饰的变量且类需要被[Serializable ]标识。

XML方法(XML Serializer)
序列化与反序列化与二进制方法十分类似。
[AppleScript] 纯文本查看 复制代码
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");
}

5.png
[AppleScript] 纯文本查看 复制代码
void ReadTest()[/align]
[align=left]{[/align]
[align=left]FileStream fs = new FileStream("demo.xml", FileMode.Open);[/align]
[align=left]XmlSerializer bf = new XmlSerializer(typeof(DemoClass));[/align]
[align=left]DemoClass demo = bf.Deserialize(fs) as DemoClass;[/align]
[align=left]fs.Close();[/align]
[align=left]demo.Output();[/align]
[align=left]}


6.png
耶,成功了!
注意:XML方法中类不需要[Serializable]标识,不能序列化私有变量,[NonSerialized]这个标识在该方法中无效。
区别:
  • 二进制方法:性能好,体积小。
  • XML方法:可读性强,但体积较大,可在无其他环境时使用。

总结
本文介绍了Unity中序列化相关的关键字及其区别和用法,C#中两种序列化与反序列化的方法。
希望大家在日常开发中合理使用SerializeField,不用滥用Public。
以上
知乎@大刀切香蕉

评分

参与人数 1鲜花 +2 收起 理由
121872426 + 2 赞一个!

查看全部评分

[发帖际遇]: 清风 发帖时在路边捡到 2 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

本帖被以下淘专辑推荐:

  • · I Like|主题: 87, 订阅: 9

跟我念“站长妹纸萌萌哒!”我说站长,你说YO!爱你们么么哒~
回复

使用道具 举报

5熟悉之中
749/1000
排名
3476
昨日变化
17

0

主题

166

帖子

749

积分

Rank: 5Rank: 5

UID
264326
好友
0
蛮牛币
1198
威望
0
注册时间
2018-1-14
在线时间
163 小时
最后登录
2019-1-19
发表于 2018-12-15 10:10:33 | 显示全部楼层

回复

使用道具 举报

7日久生情
2428/5000
排名
2430
昨日变化
9

1

主题

1548

帖子

2428

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
119154
好友
0
蛮牛币
2735
威望
0
注册时间
2015-8-21
在线时间
303 小时
最后登录
2019-1-18
发表于 2018-12-15 20:44:31 | 显示全部楼层
谢谢楼主大大。

回复

使用道具 举报

7日久生情
1580/5000
排名
2898
昨日变化
15

7

主题

515

帖子

1580

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
40014
好友
16
蛮牛币
2071
威望
0
注册时间
2014-8-15
在线时间
388 小时
最后登录
2019-1-20
QQ
发表于 2018-12-16 09:50:19 | 显示全部楼层
Unity与C#的序列化与反序列化

回复 支持 反对

使用道具 举报

5熟悉之中
887/1000
排名
2441
昨日变化
11

0

主题

114

帖子

887

积分

Rank: 5Rank: 5

UID
232255
好友
1
蛮牛币
1602
威望
0
注册时间
2017-7-15
在线时间
201 小时
最后登录
2019-1-18
发表于 2018-12-17 08:27:46 | 显示全部楼层
66666666 多谢分享

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1022/1500
排名
2613
昨日变化
6

1

主题

147

帖子

1022

积分

Rank: 6Rank: 6Rank: 6

UID
236305
好友
1
蛮牛币
1468
威望
0
注册时间
2017-8-7
在线时间
334 小时
最后登录
2019-1-18
发表于 2018-12-17 10:22:14 | 显示全部楼层
学习~~~~

回复

使用道具 举报

2初来乍到
122/150
排名
22762
昨日变化
5

0

主题

73

帖子

122

积分

Rank: 2Rank: 2

UID
252110
好友
0
蛮牛币
164
威望
0
注册时间
2017-11-2
在线时间
31 小时
最后登录
2019-1-17
发表于 2018-12-17 10:51:32 | 显示全部楼层
{:104:}{:104:}

回复

使用道具 举报

7日久生情
1833/5000
排名
933
昨日变化
1

0

主题

116

帖子

1833

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
35660
好友
0
蛮牛币
2688
威望
0
注册时间
2014-7-22
在线时间
619 小时
最后登录
2019-1-14
发表于 2018-12-17 12:24:05 | 显示全部楼层
序列化到底有什么作用呢?

回复 支持 反对

使用道具 举报

4四处流浪
319/500
排名
13094
昨日变化
7

0

主题

50

帖子

319

积分

Rank: 4

UID
157008
好友
0
蛮牛币
71
威望
0
注册时间
2016-7-15
在线时间
203 小时
最后登录
2019-1-18
QQ
发表于 2018-12-17 14:19:55 | 显示全部楼层
楼主,你的一楼有个傻逼轮子,
你处理一下。
[发帖际遇]: 一个袋子砸在了 lsz19910430 头上,lsz19910430 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

5熟悉之中
500/1000
排名
5073
昨日变化
3

0

主题

87

帖子

500

积分

Rank: 5Rank: 5

UID
282652
好友
1
蛮牛币
2805
威望
0
注册时间
2018-5-24
在线时间
135 小时
最后登录
2019-1-17
发表于 2018-12-17 14:29:07 | 显示全部楼层
序列化和反序列化

回复 支持 反对

使用道具 举报

5熟悉之中
755/1000
排名
5569
昨日变化
28

1

主题

269

帖子

755

积分

Rank: 5Rank: 5

UID
258102
好友
1
蛮牛币
905
威望
0
注册时间
2017-12-6
在线时间
239 小时
最后登录
2019-1-18
发表于 2018-12-17 14:50:53 | 显示全部楼层

回复

使用道具 举报

排名
47495
昨日变化
21

0

主题

9

帖子

15

积分

Rank: 1

UID
295780
好友
0
蛮牛币
1
威望
0
注册时间
2018-9-4
在线时间
2 小时
最后登录
2018-12-17
发表于 2018-12-17 14:58:10 | 显示全部楼层
Unity与C#的序列化与反序列化

回复 支持 反对

使用道具 举报

3偶尔光临
288/300
排名
11064
昨日变化
6

0

主题

135

帖子

288

积分

Rank: 3Rank: 3Rank: 3

UID
248391
好友
0
蛮牛币
173
威望
0
注册时间
2017-10-12
在线时间
63 小时
最后登录
2019-1-17
发表于 2018-12-17 16:26:38 | 显示全部楼层
看不太明白呀

回复

使用道具 举报

7日久生情
2521/5000
排名
480
昨日变化
1

6

主题

171

帖子

2521

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
84820
好友
17
蛮牛币
2560
威望
0
注册时间
2015-3-26
在线时间
838 小时
最后登录
2019-1-18
发表于 2018-12-17 17:12:03 | 显示全部楼层
yongzhoubaji 发表于 2018-12-17 12:24
序列化到底有什么作用呢?

其目的是以某种存储形式使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方。

回复 支持 反对

使用道具 举报

5熟悉之中
682/1000
排名
14021
昨日变化
1

1

主题

98

帖子

682

积分

Rank: 5Rank: 5

UID
1944
好友
3
蛮牛币
1279
威望
0
注册时间
2013-8-13
在线时间
526 小时
最后登录
2018-12-26
发表于 2018-12-17 21:08:16 | 显示全部楼层
转载别人的文章能不能把原文链接也发下?只是把别人ID发出来这么没诚意?

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表