Values changing after making a component

Script one:

 private void InitializeEntities()
 {
     // Get the boxIdToMaterial dictionary
     var (edgeToBoxId, boxIdToMaterial, boxIdToBox) = GetBoxIdToMaterialDictionary(quadtree);

     // Create material lookup blob
     materialLookupRef = CreateMaterialLookupBlobAsset(boxIdToMaterial);

     // Create edge lookup blob
     edgeLookupRef = CreateEdgeLookupBlobAsset(edgeToBoxId);

     // Clone the quadtree
     quadtreeBucketLists = QuadtreeCloner.CloneQuadtree(quadtree, edgeLookupRef, materialLookupRef);

    
     // Create and initialize QuadtreeData entity
     dataEntity = entityManager.CreateEntity();
     entityManager.AddComponentData(dataEntity, new QuadtreeData
     {
         BucketLists = quadtreeBucketLists.Value,
     });
    
     // Create and initialize QuadtreeLookups entity
     lookupsEntity = entityManager.CreateEntity();
     entityManager.AddComponentData(lookupsEntity, new QuadtreeLookups
     {
         EdgeLookup = edgeLookupRef,
         MaterialLookup = materialLookupRef
     });
         
      viewer.quadtreeDataEntity = dataEntity;
     viewer.quadtreeLookupsEntity = lookupsEntity;
 }

script two (viewer):

if (entityManager.HasComponent<QuadtreeData>(quadtreeDataEntity))
{
    quadtreeData = entityManager.GetComponentData<QuadtreeData>(quadtreeDataEntity);
    Debug.Log($"QuadtreeData - BucketLists Length: {quadtreeData.BucketLists.Length}");
    for (int i = 0; i < quadtreeData.BucketLists.Length; i++)
    {
        ref var bucketList = ref quadtreeData.BucketLists[i];
        Debug.Log($"BucketList {i}: Direction: {bucketList.Direction}, Dimensions: {bucketList.Dimensions.x}x{bucketList.Dimensions.y}");
    }
}

The Bucketlists have values that look like unitialized data ie direction is 1-4 and dimensions are 20 each but i am getting “BucketList 1: Direction: 64809648, Dimensions: 675x 66226096y”

I can verify that the bucketlists are correct before being added as a component

There’s not really enough context provided to know what’s going on, like whether you’re using blobs from Entities or what kind of allocation lifespan is in play. Two common scenarios for such problems are early disposal of the memory in question, and failure to store references to blob memory correctly.

For the latter case, any time that you specifically store a copy of data that contains internal pointers (BlobArray, BlobPtr, BlobString, etc) on its own is incorrect. Blobs with internal pointers must always be accessed by reference. Instead of having a component field of the data type (MyBlobType, BlobArray<T> etc.), you should always store the whole BlobAssetReference of that type (BlobAssetReference<MyBlobType>, BlobAssetReference<BlobArray<T>>, etc.) and access structures through that. Entities includes analyzers that provide errors about incorrect usage of blobs (any time you create unintentional copies of data instead of using refs for a struct containing internal pointers), but your case of using fields for everything (specifically quadtreeData in your second snippet) instead of local variables circumvents those errors. Using local variables would immediately present relevant error messages.

sorry for not posting the data structures

public struct BucketList
{
    [ReadOnly] public int Direction;
    [ReadOnly] public int2 Dimensions;
    [ReadOnly] public double2 CellSize;
    [ReadOnly] public double2 Origin;
    [ReadOnly] public BlobArray<BlobArray<QuadtreeNode>> Cells;
}
[StructLayout(LayoutKind.Sequential)]
public struct Edge
{
    [ReadOnly] public double2 Start;
    [ReadOnly] public double2 End;
    [ReadOnly] public ECSBallisticMaterial Material;
    [ReadOnly] public int BoxId;
    [ReadOnly] public Box Box;
}
[StructLayout(LayoutKind.Sequential)]
public struct Box
{
    [ReadOnly] public double2 A;
    [ReadOnly] public double2 B;
    [ReadOnly] public double2 C;
    [ReadOnly] public double2 D;
}
[StructLayout(LayoutKind.Sequential)]
public struct Door
{
    [ReadOnly] public double2 A;
    [ReadOnly] public double2 B;
    [ReadOnly] public double2 C;
    [ReadOnly] public double2 D;
    [ReadOnly] public ECSBallisticMaterial Material;
}
[StructLayout(LayoutKind.Sequential)]
public struct Hull
{
    [ReadOnly] public BlobArray<Edge> Edges;
    [ReadOnly] public ECSBallisticMaterial Material;
}

[StructLayout(LayoutKind.Sequential)]
public struct QuadtreeNode
{
    [ReadOnly] public double2 Origin;
    [ReadOnly] public double2 Size;
    [ReadOnly] public bool IsLeaf;
    [ReadOnly] public int Depth;
    [ReadOnly] public BlobArray<QuadtreeNode> Children;
    [ReadOnly] public BlobArray<Edge> Edges;
    [ReadOnly] public BlobArray<Door> Doors;
    [ReadOnly] public BlobArray<Hull> Hulls;
}
[StructLayout(LayoutKind.Sequential)]
public struct QuadtreeData : IComponentData
{
    [ReadOnly]public BlobArray<BucketList> BucketLists;
}
[StructLayout(LayoutKind.Sequential)]
public struct EdgeLookupBlob
{
    [ReadOnly] public BlobArray<Edge> Edges;
}
[StructLayout(LayoutKind.Sequential)]
public struct MaterialLookupBlob
{
    [ReadOnly] public BlobArray<ECSBallisticMaterial> Materials;
}
[StructLayout(LayoutKind.Sequential)]
public struct QuadtreeLookups : IComponentData
{
    [ReadOnly] public BlobAssetReference<EdgeLookupBlob> EdgeLookup;
    [ReadOnly] public BlobAssetReference<MaterialLookupBlob> MaterialLookup;
}

the readonly and structlayouts arent making a difference

Then my statements in the previous post apply here. Fields of a component should never be things like BlobArray or anything that includes them. Offending fields should be replaced with BlobAssetReference to the required data. Specifically QuadtreeData.BucketLists should be BlobAssetReference<BlobArray<BucketList>> or however you can redesign it to use a BlobAssetReference as a field.

Addendum, ReadOnlyAttribute is meant for annotating native container fields in job structs, they serve no purpose where you’re using them.

1 Like