[游戏开发] Unity中使用FlatBuffer

 什么是FlatBuffer

官网: 

GitHub - google/flatbuffers: FlatBuffers: Memory Efficient Serialization LibraryFlatBuffers: Memory Efficient Serialization Library - google/flatbuffersicon-default.png?t=O83Ahttps://github.com/google/flatbuffers

为什么用FloatBuffer,优势在哪?

下图是常规使用的各种数据存储类型的性能对比。 

  1. 对序列化数据的访问不需要打包和拆包——它将序列化数据存储在缓存中,这些数据既可以存储在文件中,又可以通过网络原样传输,而没有任何解析开销;(这是最主要的原因,ProtoBuffer、JSON等均需要拆包和解包)
  2. 内存效率和速度——访问数据时的唯一内存需求就是缓冲区,不需要额外的内存分配。 这里可查看详细的基准测试;
  3. 扩展性、灵活性——它支持的可选字段意味着不仅能获得很好的前向/后向兼容性(对于长生命周期的游戏来说尤其重要,因为不需要每个新版本都更新所有数据);
  4. 最小代码依赖——仅仅需要自动生成的少量代码和一个单一的头文件依赖,很容易集成到现有系统中。再次,看基准部分细节;
  5. 强类型设计——尽可能使错误出现在编译期,而不是等到运行期才手动检查和修正;
  6. 使用简单——生成的C++代码提供了简单的访问和构造接口;而且如果需要,通过一个可选功能可以用来在运行时高效解析Schema和类JSON格式的文本;
  7. 跨平台——支持C++11、Java,而不需要任何依赖库;在最新的gcc、clang、vs2010等编译器上工作良好;

 除了性能上的优势,FlatBuffer还支持把数据序列化成明文Json供开发者校验数据正确性。

游戏开发什么情况选择使用FlatBuffer 

 大量的数据配表,想要高效加载大量数据

FlatBuffer使用流程

  1. 定义FlatBuffer数据格式文件schema
  2. 序列化数据成bytes文件
  3. Unity工程中加入FlatBuffer解析源码
  4. 使用FlatC.exe工具生成C#数据解析代码
  5. 加载bytes数据解析成数据对象。

Schema

FlatBuffer的自定义数据格式文件叫Schema。文件后缀是.fbs,和protobuffer的.proto后缀类似。

Schema支持的语法有

创建MyTestData.fbs文件,放到新建文件夹TestFlatBuffer内

//统计一下所有使用类型
//namespace的作用:1生成C#代码有命名空间  2生成文件夹
namespace MyGame;//attribute字段暂时没看啥作用
attribute "priority";//枚举使用方式1
enum Color : byte { Red = 1, Green, Blue }//枚举使用方式2
enum PhoneType : int {MOBILE = 0,HOME = 1,WORK = 2,
}table Monster {number:string (required);type:int;
}table Weapon {number:string (required);type:int;
}table Pickup {number:string (required);type:int;
}//数据对象可以是Monster、Weapon、Pickup中的任何一个
union TestUnion { Monster, Weapon, Pickup }//自定义三维数据
struct Vec3 {x:float;y:float;z:float;
}//Monster结构中展示了常规值类型数据的使用方法
//展示了在table内使用struct、数组、union、枚举
table DataTable {pos:Vec3;//常规值类型damage:int = 500;hp:short = 100;name:string;friendly:bool = false;//数组的使用方式intArr:[int];//枚举的使用方式,支持写默认值color:Color = Blue;unionTarget:TestUnion;
}table MyTestData {dataTable:[DataTable];
}//root_type字段非常重要
root_type MyTestData;

Flatc.exe文件

flatc文件是干嘛的?它是把schema语法文件生成目标语言代码的程序。

Releases · google/flatbuffers · GitHubFlatBuffers: Memory Efficient Serialization Library - Releases · google/flatbuffersicon-default.png?t=O83Ahttps://github.com/google/flatbuffers/releases 

 新建一个批处理文件exportCSharp.bat去运行这个exe程序

flatc.exe --csharp -o Sample MyTestData.fbs

--csharp代表生成目标语言

-o代表输出文件路径为 Sample文件夹

在PowerSheel中运行这个bat,不在powerSheel运行就双击运行Bat文件,发现有语法错误 

修改53行语法错误继续运行bat,成功后没啥日志

到输出文件夹去看一下

通过图片可以看出,我们在Schema文件里定义的数据类型都生成了一份C#文件,把MyGame文件夹拷贝到Unity项目中就可以解析这些数据啦

打开MyTestData文件简单看一下,反正都是数据格式咱们不需要太关心。

 下载FlatBuffer源码

为何前面已经导出了schema数据代码,还要下载FlatBuffer源码??

因为schema生成的代码是纯数据相关的代码,需要源码去驱动数据代码序列化和反序列化功能。

https://github.com/google/flatbuffersicon-default.png?t=O83Ahttps://github.com/google/flatbuffers 

 把这些C#脚本拷贝到Unity项目中,多余文件可以删掉。

把源码拷贝到项目中后,编译报错

原因是我的FlatBuffer源码使用的是老版本,和flatc.exe代码的版本号不配套,你们的Flatc和FlatBuffers源码都从官网下载,肯定是配套的。

在Unity中使用FlatBuffer

完成前面的工作就可以正式使用FlatBuffer啦 

这是官方文档里推荐的Unity使用FlatBuffer案例

Flatbuffers for Unity + Sample Code | eXiinicon-default.png?t=O83Ahttp://exiin.com/blog/flatbuffers-for-unity-sample-code/

测试工程就只有FlatBuffers源码和我们生成的MyGame数据脚本

整俩按钮测试

创建一个测试文件UseFlatBuffer.cs

using System.IO;
using UnityEngine;
using MyGame;
using Google.FlatBuffers;
using Color = MyGame.Color;public class UseFlatBuffer : MonoBehaviour
{public void Serilized(){//MyTestDatas是个数组,我们假定数据有5条int dataCount = 5;FlatBufferBuilder builder = new FlatBufferBuilder(1);//创建数组对象Offset<DataTable>[] dataTables = new Offset<DataTable>[dataCount];for (int i = 0; i < dataCount; i++){StringOffset testName = builder.CreateString(i.ToString());VectorOffset inventoryVector = DataTable.CreateIntArrVector(builder,new int[]{i * 10 + 1,i * 10 + 2,i * 10 + 3,i * 10 + 4});//创建Union类型和对象TestUnion unionType = TestUnion.Monster;Offset<Monster> monster = Monster.CreateMonster(builder, builder.CreateString("怪物的名字"), 100);//---------------------开始写入数据-------------------------------------------------DataTable.StartDataTable(builder);//创建、写入posOffset<Vec3> pos = Vec3.CreateVec3(builder, 100 * i, 100 * i, 100 * i);DataTable.AddPos(builder,pos);DataTable.AddHp(builder, 2);//short类型DataTable.AddFriendly(builder,true);DataTable.AddName(builder,testName);//string类型//数组的用法DataTable.AddIntArr(builder,inventoryVector);//添加整数数组到对象//枚举的用法DataTable.AddColor(builder,Color.Red);//Union的使用方法DataTable.AddUnionTargetType(builder,unionType);DataTable.AddUnionTarget(builder, monster.Value);dataTables[i] = DataTable.EndDataTable(builder);}//把5条数据塞入VectorOffset,因为最终数据是一个数组VectorOffset dtArr = MyTestData.CreateDataTableVector(builder, dataTables);//开始写入数据MyTestData.StartMyTestData(builder);MyTestData.AddDataTable(builder,dtArr);//结束写入Offset<MyTestData> dtOffset = MyTestData.EndMyTestData(builder);//序列化数据MyTestData.FinishMyTestDataBuffer(builder,dtOffset);byte[] bytes = builder.DataBuffer.ToSizedArray();File.WriteAllBytes("E:\\MyTestData.bytes",bytes);}//反序列化,把数据都打印出来public void Deserilized(){byte[] datas = File.ReadAllBytes("E:\\MyTestData.bytes");ByteBuffer buffer = new ByteBuffer(datas);MyTestData myTestData = MyTestData.GetRootAsMyTestData(buffer);int dtCount = myTestData.DataTableLength;Debug.Log("数据量:" + dtCount.ToString());for (int i = 0; i < dtCount; i++){MyGame.DataTable dt = myTestData.DataTable(i).Value;Vec3 targetPos = dt.Pos.Value;Debug.Log(string.Format("x:{0},y:{1},z{2}",targetPos.X,targetPos.Y,targetPos.Z));for (int j = 0; j < dt.IntArrLength; j++)Debug.Log("intArr: " + dt.IntArr(j).ToString());MyGame.Color color = dt.Color;Debug.Log("color: " + color);}}
}

注意点

1、数据结构支持嵌套自身

table MyTestData {damage:int = 500;data:MyTestData;
}

2、如果你只有一个数据对象,用下面的写法,根数据就是这个结构体,如果你有多个重复对象,则用上面的写法,把它写成一个数组。

table MyTestData {dataTable:[DataTable];
}
root_type MyTestData;
table MyTestData {damage:int = 500;hp:short = 100;name:string;
}
root_type MyTestData;

3、三维数组有简写方式,官网里有写

struct Vec3 {v:[float:3];
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/488834.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JAVA】旅游行业中大数据的使用

一、应用场景 数据采集与整合&#xff1a;全面收集旅游数据&#xff0c;如客流量、游客满意度等&#xff0c;整合形成统一数据集&#xff0c;为后续分析提供便利。 舆情监测与分析&#xff1a;实时监测旅游目的地的舆情信息&#xff0c;运用NLP算法进行智能处理&#xff0c;及…

android studio创建虚拟机注意事项

emulator 启动模拟器的时候&#xff0c;可以用 AVD 界面&#xff0c;也可以用命令行启动&#xff0c;但命令行启 动的时候要注意&#xff0c;系统有两个 emulator.exe &#xff0c;建议使用 emulator 目录下的那个&#xff01;&#xff01; 创建类型为google APIs的虚拟机可从…

全面解析租赁小程序的功能与优势

内容概要 租赁小程序正在逐渐改变人与物之间的互动方式。通过这些小程序&#xff0c;用户不仅可以轻松找到所需的租赁商品&#xff0c;还能够享受无缝的操作体验。为了给大家一个清晰的了解&#xff0c;下面我们将重点介绍几个核心功能。 建议&#xff1a;在选择租赁小程序时&…

JCR一区牛顿-拉夫逊优化算法+分解对比!VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测

JCR一区牛顿-拉夫逊优化算法分解对比&#xff01;VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测 目录 JCR一区牛顿-拉夫逊优化算法分解对比&#xff01;VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.中科院…

用二维图像渲染3D场景视频

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

每日一练:链表-重排链表

LCR 026. 重排链表 - 力扣&#xff08;LeetCode&#xff09; 题目要求&#xff1a; 给定一个单链表 L 的头节点 head &#xff0c;单链表 L 表示为&#xff1a; L0 → L1 → … → Ln-1 → Ln 请将其重新排列后变为&#xff1a; L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → ……

国产物联网平台(IotSharp+IoTGateway+Influxdb)快速上手

环境说明&#xff1a; Visual Studio 2022 CommunityIotSharp代码&#xff1a;https://github.com/IoTSharp/IoTSharp.gitIoTGateway版本&#xff1a;v2.1.1Node版本&#xff1a;v20.18.1Influxdb版本&#xff1a;v2.7.11 安装Node Node.js官网 官网下载并安装&#xff0c;…

每日一刷——二叉树的构建——12.12

第一题&#xff1a;最大二叉树 题目描述&#xff1a;654. 最大二叉树 - 力扣&#xff08;LeetCode&#xff09; 我的想法&#xff1a; 我感觉这个题目最开始大家都能想到的暴力做法就是遍历找到数组中的最大值&#xff0c;然后再遍历一遍&#xff0c;把在它左边的依次找到最大…

Redis篇-6--原理篇5--单线程模型

1、概述 Redis 采用单线程模型来处理客户端请求&#xff0c;这意味着在任意时刻只有一个命令被执行。这种设计简化了 Redis 的实现&#xff0c;并确保了高并发环境下的数据一致性。尽管 Redis 是单线程的&#xff0c;但它通过高效的内存管理和网络 I/O 操作&#xff0c;仍然能…

【问题记录】07 MAC电脑,使用FileZilla(SFTP)连接堡垒机不成功

项目场景&#xff1a; 使用MAC电脑&#xff0c;以子账号&#xff08;非root&#xff09;的形式登录&#xff0c;连接堡垒机CLB&#xff08;传统型负载均衡&#xff09;&#xff0c;使用FileZilla&#xff08;SFTP&#xff09;进行FTP文件传输。 问题描述&#xff1a; MAC电脑…

Linux下进程替换exec系列接口

文章目录 Linux下进程替换1. c库exec函数族一、exec函数族简介二、exec函数族函数原型及参数说明三、exec函数族的工作机制四、注意事项五、示例代码 2. 系统调用execve接口一、execve接口与C库exec函数族的关系二、函数原型三、参数说明四、工作原理五、返回值六、注意事项七、…

网页爬虫技术全解析:从基础到实战

引言 在当今信息爆炸的时代&#xff0c;互联网上的数据量每天都在以惊人的速度增长。网页爬虫&#xff08;Web Scraping&#xff09;&#xff0c;作为数据采集的重要手段之一&#xff0c;已经成为数据科学家、研究人员和开发者不可或缺的工具。本文将全面解析网页爬虫技术&…

设计模式:24、访问者模式

目录 0、定义 1、访问者模式的五种角色 2、访问者模式的UML类图 3、示例代码 0、定义 表示一个作用于某对象结构中的各个元素的操作。它可以在不改变各个元素的类的前提下&#xff0c;定义作用于这些元素的新操作。 1、访问者模式的五种角色 抽象元素&#xff08;Element…

快速掌握Quartz.Net计划任务调度框架,轻松实现定时任务

前言 Quartz.Net是一个开源的作业调度框架&#xff0c;可以用于管理计划任务和定期执行。Quartz.Net提供了丰富的作业计划选项&#xff0c;例如精确或模糊时间表达式、日期和时间限制等。Quartz.Net采用分布式架构&#xff0c;允许在多个计算机上运行任务。 Quartz.Net架构设…

【C++】内存分布、new、delete、 operator new、operator delete

内存分布 在C语言和C中&#xff0c;程序内存被划分成六个部分&#xff1a; 内核空间、栈、内存映射段、堆、数据段、代码段 栈&#xff1a;又称堆栈&#xff0c;主要为非静态局部变量、函数参数、返回值等&#xff0c;栈的生长方向是向下生长的 内存映射段&#xff1a;高效的…

Quill富文本实现内容自定义格式format

在使用quill富文本编辑器时&#xff0c;我们输入文本会被作为类似DOM节点的数据对象存储在内部&#xff0c;渲染时生成相应的DOM节点。这是quill的文档模型Parchment,它提供了多种内容节点类型&#xff0c;如Inline \ Block \ Embed等。 quill 扩展了 Parchment 提供的的基础类…

Kael‘thas Sunstrider Ashes of Al‘ar

Kaelthas Sunstrider 凯尔萨斯逐日者 <血精灵之王> Kaelthas Sunstrider - NPC - 魔兽世界怀旧服TBC数据库_WOW2.43数据库_70级《燃烧的远征》数据库 Ashes of Alar 奥的灰烬 &#xff08;凤凰 310%速度&#xff09; Ashes of Alar - Item - 魔兽世界怀旧服TBC数据…

Rust之抽空学习系列(三)—— 编程通用概念(中)

Rust之抽空学习系列&#xff08;三&#xff09;—— 编程通用概念&#xff08;中&#xff09; 1、变量&可变性 在Rust中&#xff0c;变量默认是不可变的 fn main() {let x 5;println!("x is {}", x); }使用let来声明一个变量&#xff0c;此时变量默认是不可变…

C++ 运算符重载 (备查)

基础 运算符重载&#xff0c;就是对已有的运算符重新进行定义&#xff0c;赋予其另一种功能&#xff0c;以适应不同的数据类型。 运算符重载也可以发生函数重载。 语法&#xff1a; void operator(); //代表了被重载的运算符。函数的参数个数取决于两个因素。1)运算符是一元(一…

计算机网络之网络层超详细讲解

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 计算机网络之网络层超详细讲解 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; …