关闭

【Unity优化】为C#定制联合(Union)提高序列化速度

标签: unity优化
2977人阅读 评论(1) 收藏 举报
分类:

序列化

很多时候,我们可以通过Protobuf之类的插件来执行序列化处理,不过如果你像我一样,对代码有洁癖的话,可能就会担心这些第三方插件的处理效率问题,有时候就会尝试自己手动处理序列化。还有一种情况就是,如果你的游戏是实时联网的,需要不断网络IO,此时还是保持洁癖比较好。
其实自己手动处理序列化也不是非常麻烦。只要针对数据对象和字节数组之间可以互相转化就可以了。
那么在自己手写序列化的过程中,遇到的一个问题就是怎样转换你的数据,比如最基本的整形、浮点型这些。

BitConvertor

在Unity中,有BitStream,然而好像没有什么用处,它们好像与Unet密切相关,而Unet目前生死未卜。
在CSharp中默认为我们提供了一个BitConvertor方法。通过它可以进行基础数据类型和字节数组之间的转换。然而我并不推荐你用它,这里我简单做了一个测试来解释原因。以下的代码都是放在一个组件的Update方法中去执行。

    void testConvertFloatToBytes()
    {
        float f = 10;
        for (int i = 0; i < 1000; i++)
        {
            BitConverter.GetBytes(f);
        }
    }

这个方法在做从float到byte数组的转换。然而,你应该能看出来一些问题。它在不停制造出byte[],而数组都是个对象,因此它在不断产生GC Alloc。
如下图:
BitConverter.GetBytes

因此,当在需要连续不断进行序列化的时刻(网络游戏中),这个方法是不可以使用的。

使用联合(Union)

在CSharp中默认是没有联合(Union)的,然而我们可以构建出一个类似联合的结构体。
使用结构体布局(StructLayout)属性以及字段偏移(FieldOffset)属性就可以自己定制数据在结构体中的分布,从而定制出一个联合。

[StructLayout(LayoutKind.Explicit, Size = 4)]
struct UNum
{
    [FieldOffset(0)]
    public byte b0;
    [FieldOffset(1)]
    public byte b1;
    [FieldOffset(2)]
    public byte b2;
    [FieldOffset(3)]
    public byte b3;

    [FieldOffset(0)]
    public int i;

    [FieldOffset(0)]
    public float f;
}

此时,我们进行数据转换时,可以使用以下的方式进行转换:

    protected byte[] m_datas;
    protected int m_dReader;
    void testConvertFloatToBytes_U()
    {
        float f = 10;
        for (int i = 0; i < 1000; i++)
        {
            UNum u = new UNum();
            u.f = f;
            m_datas[m_dReader++] = u.b0;
            m_datas[m_dReader++] = u.b1;
            m_datas[m_dReader++] = u.b2;
            m_datas[m_dReader++] = u.b3;
        }
    }

这个方法不会产生任何的GC,因为它没有将结果放在小数组中,而是直接放入了一个整体缓冲区。
注意m_datas需要是足够大的缓冲区,m_dReader是缓冲区读取索引。

总结

当执行连续大量的序列化时,使用联合可以很好地避免GCAlloc产生,而且效率要比BitConvertor来的高。

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Linq 集合处理(Union)

关于Union的两种情况 一、简单值类型或者string类型处理方式(集合需要实现IEnumerable接口) #region int类型 List ints1...
  • nidexuanzhe
  • nidexuanzhe
  • 2012-12-15 16:21
  • 8130

Union和Union All到底有什么区别

以前一直不知道Union和Union All到底有什么区别,今天来好好的研究一下,网上查到的结果是下面这个样子,可是还是不是很理解,下面将自己亲自验证: Union:对两个结果集进行并集操作,不...
  • yenange
  • yenange
  • 2011-12-31 23:07
  • 13905

Linq中Union与Contact方法用法对比

文章一开始,我们来看看下面这个简单的实例。 代码片段1: int[] ints1 = { 2, 4, 9, 3, 0, 5, 1, 7 }; int[] ints2 = { 1, 3, 6, 4, ...
  • tiana0
  • tiana0
  • 2013-10-07 23:04
  • 5365

C++中的"Union" 转成C#

//C++ Union 在C#中的使用,需要注意的是:#没有union,而且对象类型不能和非对象类型对齐,而union中所有 变量偏移量是相同的,都是0。 //C++ union Myunion...
  • courageously
  • courageously
  • 2013-04-10 15:54
  • 2151

用好Lua+Unity,让性能飞起来——Lua与C#交互篇

原文链接:http://blog.uwa4d.com/archives/USparkle_Lua.html 整合Lua是目前最强大的Unity热更新方案,毕竟这是唯一可以支持iOS热更新的办法。...
  • UWA4D
  • UWA4D
  • 2017-01-11 15:55
  • 964

Unity中性能优化的一些经验与总结(脚本优化篇)

欢迎光顾本人的小站:原文链接最近一个星期,公司的项目正在做项目调优。也在不断的尝试当中找到了一些优化代码性能的思路。发现经常是在不经意的一些小地方,大大拉低了系统整体的性能。在编写Unity程序的时候...
  • u013709166
  • u013709166
  • 2017-02-09 00:10
  • 2305

【Unity优化】为C#定制联合(Union)提高序列化速度

当执行连续大量的序列化时,使用联合可以很好地避免GCAlloc产生,而且效率要比BitConvertor来的高。
  • AndrewFan
  • AndrewFan
  • 2017-03-15 16:28
  • 2977

联合体(union)的使用方法及其本质

6.本质&进阶: 根据union固定首地址和union按最大需求开辟一段内存空间两个特征,可以发现,所有表面的定义都是虚的,所谓联合体union,就是在内存给你划了一个足够用的空间,至于你怎么玩~它...
  • huqinweI987
  • huqinweI987
  • 2014-04-13 14:27
  • 103539

C语言联合体(union)的使用方法及其本质-union

一、简介 本文介绍如何在C语言联合体类型的定义与应用。 二、实验平台   1:本文如下实验所用的上位机软件为 VS2010   2:需要本文工程源码或有疑问,请加群...
  • si_zhou_qun_84342712
  • si_zhou_qun_84342712
  • 2016-11-16 15:32
  • 2855

Unity Editor 编辑器扩展 四 ScriptableObject类定制可序列化数据

目录目录 ScriptableObject类定制可序列化数据 工具类ScriptableObjectUtility 创建一个可打包的数据类YouClass 创建对应的数据类MyData 打包按钮 生成...
  • WarrenMondeville
  • WarrenMondeville
  • 2016-11-25 01:04
  • 509
    个人资料
    • 访问:87382次
    • 积分:1280
    • 等级:
    • 排名:千里之外
    • 原创:24篇
    • 转载:1篇
    • 译文:1篇
    • 评论:43条
    关于Andrew
    Unity游戏开发程序员,
    开源游戏引擎Cyclone2D作者,
    我最近在开发一款3D赛车游戏
    热爱图形学、物理学、架构等研究,
    有兴趣的同学加群:528266922。
    博客专栏
    最新评论