最新Unity DOTS教程之BlobAsset核心机制分析

发布时间 2023-12-04 09:40:30作者: 游戏开发阿博

最近DOTS发布了正式的版本, 我们来分享一下DOTS里面BlobAsset机制,方便大家上手学习掌握Unity DOTS开发。

BlobAsset 概叙

DOTS提供了BlobAsset机制来把数据生成高效的二进制数据。BlobAsset的数据是不可变的。BlobAsset只支持非托管类型数据。支持Burst编译器编译出来的类型。同时它只存储非托管类型的数据,这样使得它序列化与反序列化的性能与效率非常的块。BlobAsset也可以被entity种的component使用。

对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大佬,欢迎你来交流学习。

BlobAsset不支持如:数组, string等其它的托管对象(垃圾回收器可以回收的为托管对象),而且运行的时候不允许改变里面的数据内容。BlobAsset为了更快的加载,他只会包含传值的类型,不能包含对内部的引用与内部指针。BlobAsset除了支持标准的值类型(float, int等)以外它还支持三种特殊的类型: BlobArray, BlobPtr, BlobString。如果BlobAsest包含内部指针,编译器会报错。使用BlobAsset主要注意以下几个方面:

A: 创建一个BlobAsset,你需要先生成一个BlobBuilder,来帮助你处理计算每个数据在内存种的偏移;

总结:使用BlobBuilder来生成BlobAsset,基于BlobAssetReference来高效访问里面的数据。

BlobAsset的创建与使用

创建一个BlobAsset,按照以下步骤来进行处理即可:

BlobBuilder构造出BlobAsset,并把数据存入进去,然后再生成BlobAssetReference<T>来给用户操作数据。参考代码如下:

 struct MarketData
 {
 public float PriceOranges;
 public float PriceApples;
 }
 BlobAssetReference<MarketData> 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<MarketData>();
 // 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<MarketData>(Allocator.Persistent);
 // Make sure to dispose the builder itself so all internal memory is disposed.
 builder.Dispose();
 return result;
 }
 #endregion

如果你要存数组到BlobAsset,可以使用BlobArray来处理。数组数据内部基于索引的偏移来进行每个元素的定位。将数组存入到BlobAsset的代码如下:

 #region CreateBlobAssetWithArray
 struct Hobby
 {
 public float Excitement;
 public int NumOrangesRequired;
 }
 struct HobbyPool
 {
 public BlobArray<Hobby> Hobbies;
 }
 BlobAssetReference<HobbyPool> CreateHobbyPool()
 {
 var builder = new BlobBuilder(Allocator.Temp);
 ref HobbyPool hobbyPool = ref builder.ConstructRoot<HobbyPool>();
 // Allocate enough room for two hobbies in the pool. Use the returned BlobBuilderArray
 // to fill in the data.
 const int numHobbies = 2;
 BlobBuilderArray<Hobby> 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<HobbyPool>(Allocator.Persistent);
 builder.Dispose();
 return result;
 }
 #endregion

存储string到BlobAsset, 代码如下:

#region CreateBlobAssetWithString
 struct CharacterSetup
 {
 public float Loveliness;
 public BlobString Name;
 }
 BlobAssetReference<CharacterSetup> CreateCharacterSetup(string name)
 {
 var builder = new BlobBuilder(Allocator.Temp);
 ref CharacterSetup character = ref builder.ConstructRoot<CharacterSetup>();
 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<CharacterSetup>(Allocator.Persistent);
 builder.Dispose();
 return result;
 }
 #endregion

存储BlobPtr数据到BlobAsset,代码如下:

#region CreateBlobAssetWithInternalPointer
 struct FriendList
 {
 public BlobPtr<BlobString> BestFriend;
 public BlobArray<BlobString> Friends;
 }
 BlobAssetReference<FriendList> CreateFriendList()
 {
 var builder = new BlobBuilder(Allocator.Temp);
 ref FriendList friendList = ref builder.ConstructRoot<FriendList>();
 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<FriendList>(Allocator.Persistent);
 builder.Dispose();
 return result;
 }
 #endregion

这里的BlobPtr是基于数据的偏移来存储的;

今天的BlobAsset机制,就给大家分享到这里了,更多的DOTS系列,关注我们,持续更新!