Unity DOTS/Dots Custom Manual

UNITY DOTS - BLOB assets 에 대해 알아보자

개양반 2022. 7. 31.
728x90

BLOB assets은 무엇에 쓰는 물건일까?

Blob 자산은 스트리밍에 최적화된 바이너리 데이터 조각입니다.
데이터를 Blob 자산에 기록하면 효율적으로 로드할 수 있고 Entity에 저장된 Compoent에서 참조할 수 있는 형식으로 데이터를 저장합니다.

여럿 스레드에서 여럿 Entity에서 안전하게 읽을 수 있다.

제한 사항

Blob Asset은 구조체의 구성요소처럼 관리되는 데이터가 포함되면 안 됩니다. (List<T> 같은 것들) 또한 런타임에서 변경되지 않는 읽기 전용 데이터만 포함되어야 합니다.


BlobAsset을 생성하는 방법

  1. BlobBuilder 만들기
  2. BlobBuilder.ConstructRoot로 Asset 루트 만들기
  3. 데이터 채우기
  4. BlobBuilder.CreateBlobAssetReference 로 BlobAssetReference 만들기
  5. BlobBuilder 를 만들때 할당한 메모리 삭제
struct MarketData
{
    public float PriceOranges;
    public float PriceApples;
}

BlobAssetReference<MarketData> CreateMarketData()
{
    // 1. Builer 만들기
    var builder = new BlobBuilder(Allocator.Temp);

    // 2. 자산 루트 만들기
    ref MarketData marketData = ref builder.ConstructRoot<MarketData>();

    // 3. 데이터 채우기
    marketData.PriceApples = 2f;
    marketData.PriceOranges = 4f;

    // 4. 래퍼런스 만들기
    var result = builder.CreateBlobAssetReference<MarketData>(Allocator.Persistent);

    // 5. Builder에 할당한 메모리 해제하기
    builder.Dispose();
    return result;
}


Blob Array

Blob 구조체를 배열로 관리하는 방법에 대해 알아보자. Blob Array는 BlobAsset을 만드는 방법과 비슷하다.

  1. BlobBuilder 만들기
  2. BlobBuilder.ConstructRoot로 Asset 루트 만들기
  3. BlobArray 초기화
  4. BlobArray에 데이터 채우기
  5. BlobBuilder.CreateBlobAssetReference 로 BlobAssetReference 만들기
  6. BlobBuilder 를 만들때 할당한 메모리 삭제
// 구조체
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>();

    // Blob은 관리되지 않는 구조체를 가져야 합니다.
    // 그러므로, 배열의 크기를 지정해야 합니다.
    const int numHobbies = 2;
    BlobBuilderArray<Hobby> arrayBuilder = builder.Allocate(
    
        // Blob은 데이터를 참조할 수 있는 형식으로 저장한다. ref 키워드 입력
        ref hobbyPool.Hobbies,
        numHobbies
    );


    // Blob Array에 데이터를 채웁니다.
    arrayBuilder[0] = new Hobby
    {
        Excitement = 1,
        NumOrangesRequired = 7
    };

    arrayBuilder[1] = new Hobby
    {
        Excitement = 0.2f,
        NumOrangesRequired = 2
    };

    // 래퍼런스를 만듭니다.
    var result = builder.CreateBlobAssetReference<HobbyPool>(Allocator.Persistent);
    builder.Dispose();
    
    return result;
}

BlobString

String은 관리되는 항목으로 BlobAsset에 저장할 수 없습니다. 그래서 BlobString이라는 것을 사용합니다.

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

    // BlobString을 초기화하고 이름을 지정합니다.
    builder.AllocateString(ref character.Name, name);

    var result = builder.CreateBlobAssetReference<CharacterSetup>(Allocator.Persistent);
    builder.Dispose();
    return result;
}


BlobPtr

내부포인터를 수동으로 설정해야 하는 경우에 사용합니다.

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");

    // 가장 친한 친구로 2번 배열에 저장된 Friend를 내부포인터로 지정합니다.
    builder.SetPointer(ref friendList.BestFriend, ref arrayBuilder[2]);

    var result = builder.CreateBlobAssetReference<FriendList>(Allocator.Persistent);
    builder.Dispose();
    return result;
}


BlobAsset 에 엑세스

BlobAssetReference<T> 로 데이터에 접근할 수 있습니다. BlobAsset의 모든 부분은 참조로 액세스해야 합니다.

struct Hobbies : IComponentData
{
    public BlobAssetReference<HobbyPool> Blob;
}

float GetExcitingHobby(ref Hobbies component, int numOranges)
{
    // 사용 가능한 취미 풀에 대한 참조를 얻습니다. 
    // 그렇지 않으면 Blobarray의 내부 참조가 유효하지 않기 때문에 참조별로 전달해야합니다.
    ref HobbyPool pool = ref component.Blob.Value;

    float mostExcitingHobby = 0;
    for (int i = 0; i < pool.Hobbies.Length; i++)
    {
		// Hobby Struct는 그렇지 않기 때문에 참조없이 사용하기에 안전합니다.
        var hobby = pool.Hobbies[i];
        
        if (hobby.NumOrangesRequired > numOranges)
            continue;
            
        if (hobby.Excitement >= mostExcitingHobby)
            mostExcitingHobby = hobby.Excitement;
    }

    return mostExcitingHobby;
}

Blob Asset Reference 삭제해야 할까?

BlobBuilder.CreateBlobAssetReference를 사용하여 런타임에 할당된 모든 Blob 자산은 수동으로 삭제해야 합니다. 이것은 디스크에서 로드된 엔티티 장면의 일부로 로드된 blob 자산의 경우 다릅니다. 이러한 모든 blob 자산은 참조 카운트되고 구성 요소가 더 이상 참조하지 않으면 자동으로 해제됩니다. 수동으로 폐기해서는 안 됩니다.

댓글

💲 추천 글