跳至主要內容

如何更方便的使用 protobufjs?看了你就知道

muzzik大约 2 分钟文章网络protobufjs

怎么给 pb 消息添加消息号?

目前论坛里的方案:

  • 二次包装(消息体封装消息体)
  • 拼接消息号(拼接固定字节在消息头用于消息号解析)

我的方案:

  • 使用默认值

默认值是什么?

其实这是 protobuf 的语法特性,只需要在 ; 前面加上 [default = 默认值] 就可以定义一个属性的默认值

package test;
syntax = "proto3";

message test {
   uint32 __id = 1 [default = 100];
   string data = 2;
}

使用默认值有什么好处?

  • 更好的性能

  • 节省传输字节

  • 更方便的使用(发送/接收再也不需要关注消息号)

  • 不需要再手动定义消息号

三种方式性能对比

1w 次

10w 次

测试代码在末尾

怎么省略消息号?

  1. 首先我们必须生成 static module 的 proto 协议文件

  2. 游戏初始化时候递归遍历 proto 顶层对象,使用 Map<消息号, 消息体>

  3. 在发送的时候就可以直接取 Map 里面的消息体用来 encode,也可以用 __proto__.constructor 获取到 class 来 encode

  4. 在接收的时候,则可以使用 protobufjs.Reader 来获得消息号,再通过 Map 获取消息体 decode,这样就完全用不到消息号了,除了排错之外

怎么避免手写消息号呢?答案是自动生成,并且生成的消息号需要缓存文件,避免上下次生成的消息不一致导致热更出现问题

源码参考

protobufjs 安装/使用

推荐自动化插件

  • 包含导入式安装、NPM 安装

  • 自动监听 proto 修改构建协议文件

  • 可自定义构建流程

更多内容点击查看:https://muzzik.gitee.io/项目案例/cc-plugin-protobufjs/open in new window


测试代码

// 二次包装
{
	this._log.time_start("二次包装");
	let temp: any;

	for (let k_n = 0; k_n < for_n; ++k_n) {
		/** 消息体字节 */
		const body = test.send_data_body.encode(test.send_data_body.create({ data: "1" })).finish();

		/** 消息 */
		temp = test.send_data
			.encode(
				test.send_data.create({
					id: 100,
					body: body,
				})
			)>
			.finish();
	}
	this._log.time_end("二次包装");
}

// 拼接消息号
{
	this._log.time_start("拼接消息号");
	for (let k_n = 0; k_n < for_n; ++k_n) {
		/** 消息体字节 */
		const body = test.send_data_body.encode(test.send_data_body.create({ data: "1" })).finish();
		const buff = new ArrayBuffer(2 + body.length);
		const mess = new Uint8Array(buff);
		const data_view = new DataView(buff);

		// 设置消息号
		data_view.setUint16(0, 100);
		// 设置消息体
		mess.set(body, 2);
	}
	this._log.time_end("拼接消息号");
}

// 默认消息号
{
	this._log.time_start("默认消息号");
	let temp: any;

	for (let k_n = 0; k_n < for_n; ++k_n) {
		const body = test.test.create({ data: "1" });

		// eslint-disable-next-line no-self-assign
		body["__id"] = body["__id"];
		temp = test.test.encode(body).finish();
	}
	this._log.time_end("默认消息号");
}

📣 觉得很赞?分享给你的朋友吧!