Search Unity

Resolved Why doesn't BlobBuilderPtr exist?

Discussion in 'Entity Component System' started by braklinath, Aug 9, 2021.

  1. braklinath

    braklinath

    Joined:
    Jul 4, 2012
    Posts:
    13
    i'm trying to create a blob asset, but I don't need to store entire arrays, just a couple pieces of separate, distinct data. i've already got an array based blob asset up and working and the only different I currently have with my non-array based one is just the data allocation / assigning. BlobBuilder.Allocate(BlobArray) returns a BlobBuilderArray that you have to manually assign to after it's just been allocated, and this works.

    however BlobBuilder.Allocate(BlobPtr) only returns the basic struct of the type of data that's just been allocated. trying to create a value from this return and assigning it does nothing and only returns 0 when attempted to be used later on. If there is a way to assign actual data to this allocated Ptr memory in the blob asset, I have failed to come across them.

    if there is a way, what is it, and why isn't it consistent with the "BlobBuilderArray" method?

    if there isn't a way to assign to a single structs worth of data in a Blob Asset... why?????????

    Unity... please, can we get an update on how ECS is going and why is the entire method of creating BlobAssets such a bloody pain?

    Edit: If I want to store single pieces of non-arrayed data... do I have to do so via the Array method? why?
     
    Last edited: Aug 9, 2021
  2. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    Allocate returns a ref. To assign to the field you can assign to the call or get a local ref:
    builder.Allocate(ref root.field) = value;


    ref var newField = ref builder.Allocate(ref root.field);
    newField = value;


    My guess is you are missing the `ref` keywords which creates a copy on your stack of the empty struct allocated.

    It's not really different from BlobBuilderArray just that the additional indirection is not required when only one element is allocated.
     
  3. braklinath

    braklinath

    Joined:
    Jul 4, 2012
    Posts:
    13
    yeah i've tried that. and i've checked within the same function if I can call from the asset reference the data that's been set and that works.

    however, regarding the Array based Blob Asset I mentioned, I'm currently doing a test where I just debug.log a value from both of them (values that I know should not be 0 if they were both working right) and well, the Array based Asset is returning what I expect, while the Ptr based one is returning 0.

    somewhere along the lines once the assets been created, it's data isn't being saved or it's being deleted or something. I'm accessing both of the data in the exact same sort of approach and really the only difference is just... one Asset is array based and it's working... while the other is pointer based and it's not.
     
  4. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    Please add some code.
     
  5. braklinath

    braklinath

    Joined:
    Jul 4, 2012
    Posts:
    13
    The code that is debugging the two different Blob Assets.

    Code (CSharp):
    1.         ref TileMeshBuilder                TileData   = ref GetSingleton<TileMeshAssetReference>()      .Reference.Value;
    2.         ref EnvironmentSettingsBlobBuilder EnviroData = ref GetSingleton<EnviroSettingsAssetReference>().Reference.Value;
    3.  
    4.         Debug.Log(EnviroData.Seed.Value + " " + TileData.UVs_TileRef[3].x);
    the resulting output should be (3116 1) but it's only (0 1).

    Edit: also don't know why the Ptr approach apparently requires an additional ".Value" tagged onto the end of it while the Array approach does not.
     
  6. braklinath

    braklinath

    Joined:
    Jul 4, 2012
    Posts:
    13
    do you also want the two blob asset constructors?
     
  7. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    Yes

    The array can use the indexer which makes it's syntax nicer but is basically the same.
     
  8. braklinath

    braklinath

    Joined:
    Jul 4, 2012
    Posts:
    13
    pointer based Blob Asset - doesn't work

    Code (CSharp):
    1. [UpdateInGroup(typeof(GameObjectAfterConversionGroup))]
    2. [AlwaysSynchronizeSystem]
    3. public class EnvironmentSettingsBlobConstructor : GameObjectConversionSystem {
    4.     protected override void OnUpdate() {
    5.  
    6.         Entities.ForEach((EnviroSimAuthoring EnviroData) => { using BlobBuilder builder = new BlobBuilder(Allocator.Temp);
    7.             ref EnvironmentSettingsBlobBuilder Asset = ref builder.ConstructRoot<EnvironmentSettingsBlobBuilder>();
    8.             builder.Allocate(ref Asset.Seed) = EnviroData.Settings.Seed;
    9.             builder.Allocate(ref Asset.MapSize) = EnviroData.Settings.MapSize;
    10.             builder.Allocate(ref Asset.ChunkSize) = EnviroData.Settings.ChunkSize;
    11.             builder.Allocate(ref Asset.Octaves) = EnviroData.Settings.Octaves;
    12.             builder.Allocate(ref Asset.WaterLevel) = EnviroData.Settings.WaterLevel;
    13.             builder.Allocate(ref Asset.Position) = EnviroData.Settings.Position;
    14.             builder.Allocate(ref Asset.Lacunarity) = EnviroData.Settings.Lacunarity;
    15.             builder.Allocate(ref Asset.Persistence) = EnviroData.Settings.Persistence;
    16.             builder.Allocate(ref Asset.Scale) = EnviroData.Settings.Scale;
    17.             builder.Allocate(ref Asset.Scalar) = EnviroData.Settings.Scalar;
    18.             builder.Allocate(ref Asset.Gradience) = EnviroData.Settings.Gradience;
    19.  
    20.             BlobAssetReference<EnvironmentSettingsBlobBuilder> m_Reference = builder.CreateBlobAssetReference<EnvironmentSettingsBlobBuilder>(Allocator.Persistent);
    21.             //builder.Dispose();;
    22.  
    23.             #region Create Unique Blob Asset Entity in Destination Entity Manager
    24.             Entity gameDataEntity = DstEntityManager.CreateEntity(); // new entity
    25.             EnviroSettingsAssetReference blobAssetReferences = new EnviroSettingsAssetReference { Reference = m_Reference }; //Blob Asset Data
    26.             DstEntityManager.AddComponentData(gameDataEntity, blobAssetReferences); // Set Blob Asset Data
    27.             SceneSection Section = new SceneSection() { SceneGUID = DstEntityManager.GetSharedComponentData<SceneSection>(GetPrimaryEntity(EnviroData)).SceneGUID };
    28.             DstEntityManager.AddSharedComponentData(gameDataEntity, Section); // ^ necessary scene section data creation and setting.
    29.             #endregion
    30.         });
    31.     }
    32. }
    Array based Blob Asset - works.
    Code (CSharp):
    1. [UpdateInGroup(typeof(GameObjectAfterConversionGroup))]
    2. [AlwaysSynchronizeSystem]
    3. public class TileBlobAssetConstructor : GameObjectConversionSystem {
    4.     protected override void OnUpdate() {
    5.         Entities.ForEach((TileAuthoring TileData) => { using BlobBuilder builder = new BlobBuilder(Allocator.Temp);
    6.             ref TileMeshBuilder Asset = ref builder.ConstructRoot<TileMeshBuilder>();
    7.             BlobBuilderArray<float3> FlatArray =     builder.Allocate(ref Asset.FlatTileRef, TileData.Data.Flat_Positions.Length  );
    8.             BlobBuilderArray<float3> EdgeArray =     builder.Allocate(ref Asset.EdgeTileRef, TileData.Data.Edge_Positions.Length  );
    9.             BlobBuilderArray<float3> CorrArray =     builder.Allocate(ref Asset.EdgeCorrRef, TileData.Data.Edge_Corrections.Length);
    10.             BlobBuilderArray<float2> UVs_Array =     builder.Allocate(ref Asset.UVs_TileRef, TileData.Data.Tile_UVs_Base.Length   );
    11.             BlobBuilderArray<quaternion> RotsArray = builder.Allocate(ref Asset.Rot_TileRef, TileData.Data.Edge_Rotations.Length  );
    12.             BlobBuilderArray<int> TrisArray =        builder.Allocate(ref Asset.TrisTileRef, TileData.Data.Tile_QuadTris.Length   );
    13.             for (int i = 0; i < FlatArray.Length; i++) { FlatArray[i] = TileData.Data.Flat_Positions[i];   }
    14.             for (int i = 0; i < EdgeArray.Length; i++) { EdgeArray[i] = TileData.Data.Edge_Positions[i];   }
    15.             for (int i = 0; i < CorrArray.Length; i++) { CorrArray[i] = TileData.Data.Edge_Corrections[i]; }
    16.             for (int i = 0; i < UVs_Array.Length; i++) { UVs_Array[i] = TileData.Data.Tile_UVs_Base[i];    }
    17.             for (int i = 0; i < RotsArray.Length; i++) { RotsArray[i] = TileData.Data.Edge_Rotations[i];   }
    18.             for (int i = 0; i < TrisArray.Length; i++) { TrisArray[i] = TileData.Data.Tile_QuadTris[i];    }
    19.             BlobAssetReference<TileMeshBuilder> m_Reference = builder.CreateBlobAssetReference<TileMeshBuilder>(Allocator.Persistent);
    20.             //builder.Dispose();
    21.  
    22.             #region Create Unique Blob Asset Entity in Destination Entity Manager
    23.             Entity gameDataEntity = DstEntityManager.CreateEntity(); // new entity
    24.             TileMeshAssetReference blobAssetReferences = new TileMeshAssetReference { Reference = m_Reference }; //Blob Asset Data
    25.             DstEntityManager.AddComponentData(gameDataEntity, blobAssetReferences); // Set Blob Asset Data
    26.             SceneSection Section = new SceneSection() { SceneGUID = DstEntityManager.GetSharedComponentData<SceneSection>(GetPrimaryEntity(TileData)).SceneGUID };
    27.             DstEntityManager.AddSharedComponentData(gameDataEntity, Section); // ^ necessary scene section data creation and setting.
    28.             #endregion
    29.         });
    30.     }
    31. }
    they are taking their source data from Scriptable Objects, and the Builders a simple structs with BlobArrays and BlobPtrs comprising the data made up within them.
     
  9. braklinath

    braklinath

    Joined:
    Jul 4, 2012
    Posts:
    13
    alright welp. I ended up messing around with the authoring gameobjects in the subscenes these two source scriptable objects were being held in, and ended up reimporting the subscene and I guess... that fixed it. it's working as it should.

    was under the impression that needing to reimport the subscenes just wasn't a necessity so it never crossed my mind that there would be an issue there (don't even know if there was one with the subscene, i'm just assuming) but well, it's an in-development piece of tech so beggars can't be choosers. thanks for trying to help though Julian.

    I'll make sure to keep in mind the possibility of needing to reimport subscene entities.
     
    julian-moschuering likes this.
  10. braklinath

    braklinath

    Joined:
    Jul 4, 2012
    Posts:
    13
    Resolved post.

    I still question the inconsistency tho.
     
  11. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    When you change code that changes conversion you need to bump the version number on the system. The data is cached so if you don't inform the system that the conversion code has changed it won't regenerate.
     
  12. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    @Joachim_Ante Is there any plan to make it auto in future or it will continue to be like that?