【Unity开发字典】序列化基类

文章目录

概要

在 数据传输,数据储存方面, 将数据序列化为字节, 是必不可少的步骤;

本文提供了一个序列化基类, 需要序列化的类可以通过, 继承此基类, 实现基类中的虚函数, 实现便捷的序列化操作, 本文在提供基类外, 还附一个案例

基类代码

下面是预览图片, 代码段会附在后边

需要重写的方法

1.public abstract int GetBytesNum();

2.public abstract byte\[\] Writing();

3.public abstract int Reading(byte\[\] bytes,int beginIndex = 0);
方法一 :子类重写, 要返回自己序列化后的长度, 创建接收序列化类的容器时,需要使用这个长度来初始化.
方法2: 子类重写, 用下面的序列化工具方法, 在方法2中, 对自己的成员变量进行序列化操作, 返回的是一个二进制字节数组.
方法3: 接收到相应类的字节数组后, 该方法通过下面的解析工具方法 , 对本类型的字节数组 , 进行解读操作, 返回当前Index(索引)位置, 可以方便后续的读取操作
方法3参数:byte\[\]bytes , 要解读的字节数组, beginIndex 从哪里开始读,默认为0

序列化读写工具

这里只写了常用的数据类型的工具, 可以按照需求写更多, 这里不一样的是,
自定义类的写入 , 自定义类的解读

思路也很简单, 直接调用自定义类里实现的写入和解读, 就可以实现.

写入参数解析:
参数1: byte\[\]bytes, 传入一个字节数组, 将序列化后的字节, 写入该字节数组;
参数2: 需要序列化的不同类型的信息, 会在方法里进行相应序列化;
参数3: ref int index 当前索引 位置,用于记录当前位于字节数组的哪个位置,用于多次记录时, 准确拼接信息到字节数组末尾;

csharp 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;


public abstract class BaseData {
    /// <summary>
    /// 子类重写, 获取字节数组容器大小
    /// </summary>
    /// <returns></returns>
    public abstract int GetBytesNum();
    /// <summary>
    /// 子类重写, 把成员变量序列为对应字节数组
    /// </summary>
    /// <returns></returns>
    public abstract byte[] Writing();
    /// <summary>
    /// 把2进制字节数组,解析到成员变量中
    /// </summary>
    /// <param name="bytes">字节数组</param>
    /// <param name="beginIndex">开始位置,默认是0</param>
    /// <returns></returns>
    public abstract int Reading(byte[] bytes,int beginIndex = 0);


    protected void WriteInt(byte[] bytes, int value, ref int index) {
        BitConverter.GetBytes(value).CopyTo(bytes, index);
        index += sizeof(int);
    }
    protected void WriteShort(byte[] bytes, short value, ref int index) {
        BitConverter.GetBytes(value).CopyTo(bytes, index);
        index += sizeof(short);
    }
    protected void WriteFloat(byte[] bytes, float value, ref int index) {
        BitConverter.GetBytes(value).CopyTo(bytes, index);
        index += sizeof(float);
    }
    protected void WriteBool(byte[] bytes, bool value, ref int index) {
        BitConverter.GetBytes(value).CopyTo(bytes, index);
        index += sizeof(bool);
    }
    protected void WriteString(byte[] bytes, string value, ref int index) {
        byte[] strbyte = Encoding.UTF8.GetBytes(value);
        BitConverter.GetBytes(strbyte.Length).CopyTo(bytes, index);
        index += sizeof(int);
        strbyte.CopyTo(bytes, index);
        index += strbyte.Length;
    }

    /// <summary>
    /// 自定义类的写入
    /// </summary>
    /// <param name="bytes">要写入的字节数组</param>
    /// <param name="data">此类已经继承BaseData 填写这个类进来</param>
    /// <param name="index">参数</param>
    protected void WriteData(byte[] bytes, BaseData data, ref int index) {
        data.Writing().CopyTo(bytes, index);
        index += data.GetBytesNum();
    }

    protected int ReadInt(byte[]bytes, ref int index) {
        int value = BitConverter.ToInt32(bytes,index);
        index += sizeof(int);
        return value;
    }
    protected short ReadShort(byte[] bytes, ref int index) {
        short value = BitConverter.ToInt16(bytes,index);
        index += sizeof(short);
        return value;
    }
    protected float ReadFloat(byte[] bytes, ref int index) {
        float value = BitConverter.ToSingle(bytes, index);
        index += sizeof(float);
        return value;
    }
    protected bool ReadBool(byte[] bytes, ref int index) {
        bool value = BitConverter.ToBoolean(bytes, index);
        index += sizeof(bool);
        return value;
    }
    protected string ReadString(byte[] bytes, ref int index) {
        int strCount = BitConverter.ToInt32(bytes,index);
        index += 4;
        string str = Encoding.UTF8.GetString(bytes, index, strCount);
        index += strCount;
        return str;
    }
    protected T ReadData<T>(byte[] bytes, ref int index) where T : BaseData , new() {
        T data = new T();
        index += data.Reading(bytes,index);
        return data;
    }


}

案例Player

PlayerData 就是继承BaseData 需要序列化的案例

需要的方法

1.public abstract int GetBytesNum();

2.public abstract byte\[\] Writing();

3.public abstract int Reading(byte\[\] bytes,int beginIndex = 0);

1.返回字节长度,

4+4+4+Str(序列化)

atk + lev + str长度(int) + 序列化后的str

2.写入, 创建一个 字节长度大小的数组, 将所有内容写入其中

3.解读 , 返回当前index变化, 连续解读时, 需要用, 给自己成员变量赋值.

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using System.Text;


public class PlayerData : BaseData
{
    public string name;
    public int atk;
    public int lev;
    public override int GetBytesNum()
    {
        
        return 4+4+4+Encoding.UTF8.GetBytes(name).Length;
    }
    public override int Reading(byte[] bytes, int beginIndex = 0)
    {
        int index = beginIndex;
        name = ReadString(bytes,ref index);
        atk = ReadInt(bytes,ref index);
        lev = ReadInt(bytes,ref index);
        return index - beginIndex;
    }
    
    public override byte[] Writing()
    {
        int index = 0;
        byte[] bytes = new byte[GetBytesNum()];
        WriteString(bytes, name, ref index);
        WriteInt(bytes,atk,ref index);
        WriteInt(bytes,lev,ref index);
        return bytes;
    }
}

在外部调用举例

csharp 复制代码
                PlayerData data= new PlayerData();
                data.Reading(receiveBytes , 0);
                print(data.name);
                print(data.atk);
                print(data.lev);

结语

现在就可以直接复制, 让你的类序列化为二进制了, 接下来我还有几篇文章, 是关于网络开发中的信息传输, 这个是第一篇

相关推荐
贪玩的蛋挞6 小时前
C#与闭包
开发语言·c#
忧郁的紫菜11 小时前
基础实现:单篇 Markdown 转 Word
开发语言·c#·word
甜美的小天鹅11 小时前
Swifter C#之inline还是不inline,这是个问题
开发语言·c#
liulilittle13 小时前
KCC 拥塞控制算法缺陷修复记录(26/07/05)
网络·tcp/ip·计算机网络·c·信息与通信·tcp·通信
翼帆16 小时前
.NET 程序保护实战系列01-流水线架构与保护引擎总览
c#·破解
落寞的电源17 小时前
Delegate = Object + MethodInfo
开发语言·数据库·c#
Denuin多啦咧梦18 小时前
玩转 .NET 依赖注入:Microsoft.Extensions.DependencyInjection 深度指南
c#·.net·依赖注入
Ricky_Theseus19 小时前
Trie 字典树:前缀匹配利器
开发语言·c#
郝学胜-神的一滴19 小时前
[简化版 GAMES 101] 计算机图形学 16:纹理走样、Mipmap、三线性插值、各向异性过滤原理全解
unity·游戏引擎·godot·图形渲染·three.js·opengl·unreal
北域码匠1 天前
嵌入式限幅滤波:工业信号降噪利器
c#·传感器采集·数据预处理·嵌入式算法·限幅滤波·数字滤波·数据降噪