Unity DOTS系列之BlobAsset核心機制分析
??最近DOTS發(fā)布了正式的版本, 我們來分享一下DOTS里面BlobAsset機制,方便大家上手學(xué)習(xí)掌握Unity DOTS開發(fā)。
BlobAsset 概敘
DOTS提供了BlobAsset機制來把數(shù)據(jù)生成高效的二進制數(shù)據(jù)。BlobAsset的數(shù)據(jù)是不可變的。BlobAsset只支持非托管類型數(shù)據(jù)。支持Burst編譯器編譯出來的類型。同時它只存儲非托管類型的數(shù)據(jù),這樣使得它序列化與反序列化的性能與效率非常的塊。BlobAsset也可以被entity種的component使用。
???BlobAsset不支持如:數(shù)組,?string等其它的托管對象(垃圾回收器可以回收的為托管對象),而且運行的時候不允許改變里面的數(shù)據(jù)內(nèi)容。BlobAsset為了更快的加載,他只會包含傳值的類型,不能包含對內(nèi)部的引用與內(nèi)部指針。BlobAsset除了支持標準的值類型(float, int等)以外它還支持三種特殊的類型:?BlobArray, BlobPtr, BlobString。如果BlobAsest包含內(nèi)部指針,編譯器會報錯。使用BlobAsset主要注意以下幾個方面:
??A: 創(chuàng)建一個BlobAsset,你需要先生成一個BlobBuilder,來幫助你處理計算每個數(shù)據(jù)在內(nèi)存種的偏移;
??B: 當你要使用一個BlobAsset的時候你需要使用ref BlobAssetReference, 來訪問BlobAsset種的數(shù)據(jù),這樣訪問數(shù)據(jù)的時候是基于BlobAsset內(nèi)部引用的不會有值的copy;
總結(jié):使用BlobBuilder來生成BlobAsset,基于BlobAssetReference來高效訪問里面的數(shù)據(jù)。 ?
?
BlobAsset的創(chuàng)建與使用
創(chuàng)建一個BlobAsset,按照以下步驟來進行處理即可:
??step1: 創(chuàng)建一個BlobBuilder,它內(nèi)部也會分配一些內(nèi)存出來;
??step2: 使用BlobBuilder.ContructRoot 函數(shù)來構(gòu)建一個root blobasset出來。
??Step3: 把數(shù)據(jù)填寫到blobasset種,保存起來;
??Step4: 使用BlobBuilder.CreateBlobAssetReference來創(chuàng)建一個BlobAssetReference來方便讀取與使用Blobasset種的數(shù)據(jù);
??Step5: 把BlobBuilder對象釋放掉。
BlobBuilder構(gòu)造出BlobAsset,并把數(shù)據(jù)存入進去,然后再生成BlobAssetReference來給用戶操作數(shù)據(jù)。參考代碼如下:
?struct?MarketData
????{
??????public?float?PriceOranges;
??????public?float?PriceApples;
????}
?
????BlobAssetReference?CreateMarketData()
????{
??????// Create a new builder that will use temporary memory to construct the blob asset
??????var?builder?= new?BlobBuilder(Allocator.Temp);
?
??????// Construct the root object for the blob asset. Notice the use of `ref`.
??????ref?MarketData?marketData?= ref?builder.ConstructRoot();
?
??????// Now fill the constructed root with the data:
??????// Apples compare to Oranges in the universally accepted ratio of 2 : 1 .
??????marketData.PriceApples?= 2f;
??????marketData.PriceOranges?= 4f;
?
??????// Now copy the data from the builder into its final place, which will
??????// use the persistent allocator
??????var?result?= builder.CreateBlobAssetReference(Allocator.Persistent);
?
??????// Make sure to dispose the builder itself so all internal memory is disposed.
??????builder.Dispose();
??????return?result;
????}
????#endregion
?
如果你要存數(shù)組到BlobAsset,可以使用BlobArray來處理。數(shù)組數(shù)據(jù)內(nèi)部基于索引的偏移來進行每個元素的定位。將數(shù)組存入到BlobAsset的代碼如下:
?#region?CreateBlobAssetWithArray
????struct?Hobby
????{
??????public?float?Excitement;
??????public?int?NumOrangesRequired;
????}
?
????struct?HobbyPool
????{
??????public?BlobArray?Hobbies;
????}
?
????BlobAssetReference?CreateHobbyPool()
????{
??????var?builder?= new?BlobBuilder(Allocator.Temp);
??????ref?HobbyPool?hobbyPool?= ref?builder.ConstructRoot();
?
??????// Allocate enough room for two hobbies in the pool. Use the returned BlobBuilderArray
??????// to fill in the data.
??????const?int?numHobbies?= 2;
??????BlobBuilderArray?arrayBuilder?= builder.Allocate(
????????ref?hobbyPool.Hobbies,
????????numHobbies
??????);
?
??????// Initialize the hobbies.
?
??????// An exciting hobby that consumes a lot of oranges.
??????arrayBuilder[0]?= new?Hobby
??????{
????????Excitement?= 1,
????????NumOrangesRequired?= 7
??????};
?
??????// A less exciting hobby that conserves oranges.
??????arrayBuilder[1]?= new?Hobby
??????{
????????Excitement?= 0.2f,
????????NumOrangesRequired?= 2
??????};
?
??????var?result?= builder.CreateBlobAssetReference(Allocator.Persistent);
??????builder.Dispose();
??????return?result;
????}
????#endregion
存儲string到BlobAsset, 代碼如下:
#region?CreateBlobAssetWithString
????struct?CharacterSetup
????{
??????public?float?Loveliness;
??????public?BlobString?Name;
????}
?
????BlobAssetReference?CreateCharacterSetup(string?name)
????{
??????var?builder?= new?BlobBuilder(Allocator.Temp);
??????ref?CharacterSetup?character?= ref?builder.ConstructRoot();
?
??????character.Loveliness?= 9001;?// it's just a very lovely character
?
??????// Create a new BlobString and set it to the given name.
??????builder.AllocateString(ref?character.Name,?name);
?
??????var?result?= builder.CreateBlobAssetReference(Allocator.Persistent);
??????builder.Dispose();
??????return?result;
????}
????#endregion
存儲BlobPtr數(shù)據(jù)到BlobAsset,代碼如下:
#region?CreateBlobAssetWithInternalPointer
????struct?FriendList
????{
??????public?BlobPtr?BestFriend;
??????public?BlobArray?Friends;
????}
?
????BlobAssetReference?CreateFriendList()
????{
??????var?builder?= new?BlobBuilder(Allocator.Temp);
??????ref?FriendList?friendList?= ref?builder.ConstructRoot();
?const?int?numFriends?= 3;
??????var?arrayBuilder?= builder.Allocate(ref?friendList.Friends,?numFriends);
??????builder.AllocateString(ref?arrayBuilder[0],?"Alice");
??????builder.AllocateString(ref?arrayBuilder[1],?"Bob");
??????builder.AllocateString(ref?arrayBuilder[2],?"Joachim");
?
??????// Set the best friend pointer to point to the second array element.
??????builder.SetPointer(ref?friendList.BestFriend,?ref?arrayBuilder[2]);
?
??????var?result?= builder.CreateBlobAssetReference(Allocator.Persistent);
??????builder.Dispose();
??????return?result;
????}
????#endregion
這里的BlobPtr是基于數(shù)據(jù)的偏移來存儲的;
今天的BlobAsset機制,就給大家分享到這里了,更多的DOTS系列,關(guān)注我,持續(xù)更新!
??
?
標簽: