[游戲開發] 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.pswp.cn/web/62675.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/62675.shtml
英文地址,請注明出處:http://en.pswp.cn/web/62675.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL其一,概念學習,可視化軟件安裝以及增刪改查語句

目錄 MySQL 1、數據庫的概念 2、數據庫分類 3、MySQL的安裝 4、安裝過程中的問題 DataGrip的使用&#xff1a; SQLynx的使用&#xff1a; 5、編寫SQL語句 6、DDL語句 7、DML 新增數據&#xff1a; 刪除數據&#xff1a; 修改數據&#xff1a; MySQL SQL其實是一門…

05 在 Linux 使用 AXI DMA

DMA簡介 DMA 是一種采用硬件實現存儲器與存儲器之間或存儲器與外設之間直接進行高速數據傳輸的技術&#xff0c;傳輸過程無需 CPU 參與&#xff08;但是CPU需要提前配置傳輸規則&#xff09;&#xff0c;可以大大減輕 CPU 的負擔。 DMA 存儲傳輸的過程如下&#xff1a; CPU 向…

linux 安裝 vsftpd 服務以及配置全攻略,vsftpd 虛擬多用戶多目錄配置,為每個用戶配置不同的使用權限

linux 安裝 vsftpd 服務以及配置全攻略&#xff0c;vsftpd 虛擬多用戶多目錄配置&#xff0c;為每個用戶配置不同的使用權限。 linux 安裝 vsftpd 服務以及配置全攻略 FTP 是 File Transfer Protocol 的簡稱&#xff0c;用于 Internet 上的控制文件的雙向傳輸。同時&#xff0…

SQL語句在MySQL中如何執行

MySQL的基礎架構 首先就是客戶端&#xff0c;其次Server服務層&#xff0c;大多數MySQL的核心服務都在這一層&#xff0c;包括連接、分析、優化、緩存以及所有的內置函數&#xff08;時間、日期、加密函數&#xff09;&#xff0c;所有跨存儲引擎功能都在這一層實現&#xff1…

ragflow連不上ollama的解決方案

由于前期wsl默認裝在C盤&#xff0c;后期部署好RagFlow后C盤爆紅&#xff0c;在連接ollama的時候一直在轉圈圈&#xff0c;問其他人沒有遇到這種情況&#xff0c;猜測是因為內存不足無法加載模型導致&#xff0c;今天重新在E盤安裝wsl 使用wsl裝Ubuntu Win11 wsl-安裝教程 如…

力扣-漢明距離

1.兩個整數之間的 漢明距離 指的是這兩個數字對應二進制位不同的位置的數目。 給你兩個整數 x 和 y&#xff0c;計算并返回它們之間的漢明距離。 看到這題&#xff0c;當然想到了按位異或^,并且c內置了計算二進制數中1數量的函數__builtin_popcount() class Solution { publ…

關于成功插入 SQLite 但沒有數據的問題

背景 技術棧&#xff1a;SpringBoot Mybatis-flex SQLite 項目中集成了SQLite&#xff0c;配置如下&#xff1a; spring:datasource:url: jdbc:sqlite::resource:db/project.dbdriver-class-name: org.sqlite.JDBC在進行測試時&#xff0c;使用Mybatis-flex往表中插入數據&…

C#常見錯誤—空對象錯誤

System.NullReferenceException&#xff1a;未將對象引用設置到對象的實例 在C#編程中&#xff0c;System.NullReferenceException是一個常見的運行時異常&#xff0c;其錯誤信息“未將對象引用設置到對象的實例”意味著代碼試圖訪問一個未被初始化或已被設置為null的對象的成…

沁恒CH32V208藍牙串口透傳例程:修改透傳的串口;UART-CH32V208-APP代碼分析;APP-CH32V208-UART代碼分析

從事嵌入式單片機的工作算是符合我個人興趣愛好的,當面對一個新的芯片我即想把芯片盡快搞懂完成項目賺錢,也想著能夠把自己遇到的坑和注意事項記錄下來,即方便自己后面查閱也可以分享給大家,這是一種沖動,但是這個或許并不是原廠希望的,盡管這樣有可能會犧牲一些時間也有哪天原…

Scala的隱式對象

Scala中&#xff0c;隱式對象&#xff08;implicit object&#xff09;是一種特殊的對象&#xff0c;它可以使得其成員&#xff08;如方法和值&#xff09;在特定的上下文中自動可用&#xff0c;而無需顯式地傳遞它們。隱式對象通常與隱式參數和隱式轉換一起使用&#xff0c;以…

矩陣的乘(包括乘方)和除

矩陣的乘分為兩種&#xff1a; 一種是高等代數中對矩陣的乘的定義&#xff1a;可以去這里看看包含矩陣的乘。總的來說&#xff0c;若矩陣 A s ? n A_{s*n} As?n?列數和矩陣 B n ? t B_{n*t} Bn?t?的行數相等&#xff0c;則 A A A和 B B B可相乘&#xff0c;得到一個矩陣 …

DVWA親測sql注入漏洞

LOW等級 我們先輸入1 我們加上一個單引號&#xff0c;頁面報錯 我們看一下源代碼&#xff1a; <?php if( isset( $_REQUEST[ Submit ] ) ) { // Get input $id $_REQUEST[ id ]; // Check database $query "SELECT first_name, last_name FROM users WHERE user_id …

C++,提供函數接口,函數如何做到接收外部變量隨時結束

在C中&#xff0c;如果你想要創建一個函數&#xff0c;該函數可以接收外部變量并在變量改變時作出響應&#xff0c;你可以使用回調函數或者將變量包裝在可以觀察其變化的設計模式中&#xff0c;例如觀察者模式。 以下是一個使用標準庫中的std::function和std::bind來創建響應外…

機器學習01-發展歷史

機器學習01-發展歷史 文章目錄 機器學習01-發展歷史1-傳統機器學習的發展進展1. 初始階段&#xff1a;統計學習和模式識別2. 集成方法和核方法的興起3. 特征工程和模型優化4. 大規模數據和分布式計算5. 自動化機器學習和特征選擇總結 2-隱馬爾科夫鏈為什么不能解決較長上下文問…

想了解操作系統,有什么書籍推薦?

推薦一本操作系統經典書&#xff1a; 操作系統導論 《操作系統導論》虛擬化(virtualization)、并發(concurrency)和持久性(persistence)。這是我們要學習的3個關鍵概念。通過學習這3個概念&#xff0c;我們將理解操作系統是如何工作的&#xff0c;包括它如何決定接下來哪個程序…

[Collection與數據結構] 位圖與布隆過濾器

&#x1f338;個人主頁:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;?熱門專欄: &#x1f9ca; Java基本語法(97平均質量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection與…

【大數據學習 | 面經】Spark的shuffle hash join的具體細節

1. 前言 shuffle hash join是Spark中一種常見的連接策略&#xff0c;尤其適用于兩個數據集都比較大且無法通過廣播來優化的情況。其核心思想是通過對連接鍵進行哈希分區&#xff0c;使得相同鍵值的數據被分配到相同的分區中&#xff0c;從而可以在每個分區獨立的執行連接操作。…

設計模式從入門到精通之(一)工廠模式

工廠模式&#xff1a;為每個工廠找到"生意經" 在現實生活中&#xff0c;我們隨處可見"工廠"的影子&#xff0c;比如汽車工廠生產汽車&#xff0c;食品工廠生產食品。但你有沒有想過&#xff0c;為什么我們需要工廠&#xff1f;如果沒有工廠&#xff0c;我們…

談談你對vue這種框架理解

發現寶藏 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。【寶藏入口】。 Vue.js 是一個漸進式的前端 JavaScript 框架&#xff0c;旨在通過提供易于理解、上手簡單且功能強大的工具來構建現代化的 Web …

使用html2canvas實現前端截圖

一、主要功能 網頁截圖&#xff1a;html2canvas通過讀取DOM結構和元素的CSS樣式&#xff0c;在客戶端生成圖像&#xff0c;不依賴于服務端的渲染。它可以將指定的DOM元素渲染為畫布&#xff08;canvas&#xff09;&#xff0c;并生成圖像。多種輸出格式&#xff1a;生成的圖像…