MessageData

MessageBundle的介绍以及在Unity中的使用

在使用一段时间的MessageData后,Berry决定对MessageData进行一次优化。之前的文章介绍过,MessageData依赖Object进行解析和打包,而Obejct的class在发布后是不太好修改的,也就是在使用动态语言进行热修复时,使用过MessageData的部分是不能进行修改的。

 

MessageBundle与MessageData的对比

这两者最大的区别在于数据解析上,而两者最终转换后的byte数据是一样的。

MessageData交换数据的核心是Object,通过反射Object能够得到数据对象所有的Field信息,然后根据Field的类型及数据进行相应的字节转换。

 

相比MessageData,MessageBundle取消了对Object的依赖,而依赖于数据模板,最终完成的是MessageStruct或MessageArray与byte数据的转换。在上面的图解中可以看到,MessageBundle中引入了数据模板,MessageStruct,MessageArray这三个部分。

1)数据模板

数据模板其实就是描述了一组数据结构的文本数据,这么描述似乎有点奇怪,看一下它的定义就能很轻松的明白

message User {

string name;

int age;

float score;

}

上面这个结构就是描述了一个User类型的数据结构,它包含了三个属性字段。其实与class的定义有些类似,以message标识符开头,后面跟模板名字,没有访问修饰符。

MessageBundle的数据模板(message)支持定义int,float,bool,string,list,以及另一个message类型数据。数据模板的作用就是代替class来描述数据结构。

2)MessageStruct

在MessageBundle中一个MessageStruct用来描述一组模板数据的内容,比如上面的User就可以用MessageStruct来进行相应的转换,而MessageStruct的创建也要依赖于message数据模板。

3)MessageArray

用来描述一个List列表类型的结构,同样的MessageAarry的泛型数据可以为int,float,bool,string,MessageArray和MessageStruct。

MessageBundle在Unity中的使用

将MesssageBundle的packet文件导入到Unity的Assets目录下,MessageBunlde默认加载模板文件的目录在Resources\Message这个目录下,在Assets下创建这一目录

接下来在Message目录下添加User.txt文件并写入一下内容

message User {

string name;

int age;

float score;

}

我们来根据这个User结构来进行数据交换

    private void Test1() {

        //根据"User"结构来创建MessageStruct并添加数据
        MessageStruct userStruct = MessageStruct.CreateMessageStruct("User");
        userStruct.PutString("name", "berry");
        userStruct.PutInt("age",1);
        userStruct.PutFloat("score",6.6f);

        //根据userStruct来创建MessageBundle并将其转换为字节数据
        MessageBundle userBundle = MessageBundle.CreateMessageBundle(userStruct);
        byte[] data = userBundle.ToDataBytes();

        //根据字节数据创建MessageBundle并将字节数据打包成"User"模板结构
        MessageBundle emptyBundle = MessageBundle.CreateMessageBundle(data);
        MessageStruct emptyStruct = emptyBundle.PacketMessageStruct("User");

        //取出转换后emptyStruct中的数据
        Debug.Log(emptyStruct.GetString("name"));
        Debug.Log(emptyStruct.GetFloat("score"));
        Debug.Log(emptyStruct.GetInt("age"));
    }

Test1这个方法完成了一次MessageStruct->byte数据->MessageStruct的交换。

User这个数据模板中有三个字段属性name(string类型)、age(int类型)、socre(float类型),通过调用MessageStruct的CreateMessageStruct方法并传入参数(这个参数为模板结构的名字),可以直接创建一个User结构的MessageStruct 。使用Putxxx方法可以添加相应类型的数据,需要注意的是Putxxx方法的第一个参数必须为User模板存在的字段属性名称,第二个参数为相应类型的数据。

通过MessageBundle可以将创建的MessageStruct转换成字节数据,也可以将字节数据转换成相应的MessageStruct。PacketMessageStruct方法(传入模板结构的名字)可以将byte数据转换成相应的MessageStruct,调用Getxxx方法可得到相应的数据

接下来看看MessageArray

顾名思义,MessageArray用来貌似列表结构,我们来加入Room.txt这个数据模板

message Room {
string roomName;
List<User> users;
}
 Room中包含了一个泛型为User的List,User表示一个MessageStruct,而List这一关键字会被MessageBundle解析为MessageArray,也就是说MessageArray的列表项其实就是MessageBundle。
    private void Test2() {

        //根据"Room"结构来创建MessageStruct并添加数据
        MessageStruct roomStruct = MessageStruct.CreateMessageStruct("Room");
        roomStruct.PutString("roomName","树莓屋");
        //创建一个User模板数据的MessageArray
        MessageArray userArray = MessageArray.CreateMessageArray("User");
        //创建两个UserStruct
        MessageStruct userStruct1 = MessageStruct.CreateMessageStruct("User");
        userStruct1.PutString("name","user1");   //设置参数name的值
        userStruct1.PutInt("age",15);        //设置参数age的值
        userStruct1.PutFloat("score",5.6f);   //设置参数score的值
        MessageStruct userStruct2 = MessageStruct.CreateMessageStruct("User");
        userStruct2.PutString("name", "user2");
        userStruct2.PutInt("age", 9);
        userStruct2.PutFloat("score", 9.5f);
        //往userArray中添加这两个UserStruct
        userArray.AddMessageStruct(userStruct1);
        userArray.AddMessageStruct(userStruct2);

        roomStruct.PutMessageArray("users",userArray);   //设置参数users的值

        byte[] data = MessageBundle.CreateMessageBundle(roomStruct).ToDataBytes();

        //根据byte数据创建MessageBundle并将其装换成Room类型的MessageStruct
        MessageBundle emptyBundle = MessageBundle.CreateMessageBundle(data);
        MessageStruct emptyStruct = emptyBundle.PacketMessageStruct("Room");
        Debug.Log(emptyStruct.GetString("roomName"));
        for (int i = 0; i < emptyStruct.GetMessageArray("users").Count; i++) {
            Debug.Log(emptyStruct.GetMessageArray("users").GetMessageStruct(i).GetString("name"));
            Debug.Log(emptyStruct.GetMessageArray("users").GetMessageStruct(i).GetInt("age"));
            Debug.Log(emptyStruct.GetMessageArray("users").GetMessageStruct(i).GetFloat("score"));
        }
    }

Test2方法演示了使用MessageArray来处理List类型数据。看到这里我们会发现MessageBundle中的MessageStruct和MessageArray跟Json中的JsonObject和JsonArray有些相似,实际上berry在设计MessageBundle时就是希望我们在使用过程中更好的接受和理解MessageBundle。

MessageData和MessageBundle的选择

MessageBundle是MessageData的延伸版本,它们转换相同结构的数据得到的byte数据是一样的,也就是说这两者可以互相装换。相对来说MessageData的使用要比MessageBundle简单许多,转换效率相对较高。MessageBundle脱离的对object的依赖使用起来更加灵活,也可以结合动态语言来进行使用。

(3)

本文由 树莓屋 作者:Berry贝锐 发表,转载请注明来源!

关键词:,

热评文章

发表评论