Good afternoon!
I was recently trying to implement a number of ICleanupComponent instances to help simplify queries for deleting entities from the world.
I ran into a scenario where one of the components I’d like to clean up is basically on the entity for it’s entire lifetime. It can be added during baking or attached at runtime. This is a struct that contains a BlobAssetReference, when the blob is created at runtime I’d like to dispose of the blob when the entity is destroyed.
Here is an example of a query I’m using. The type “HeightMap” needs to be cleaned up but if I change the definition of HeightMap to implement ICleanupComponent, and pass the query to state.RequireForUpdate(generateQuery), then OnUpdate is never called. Even when the component is definitely present on the entity.
HeightMap is a struct and considered “unmanaged”.
generateQuery = SystemAPI.QueryBuilder()
.WithAll<MeshTerrain, MaterialMeshInfo, RenderBounds, HeightMap, GenerateMesh>()
.WithNone<MeshResult>()
.Build();
To add to my confusion, I have another component “MeshReference” that is a managed component that implements ICleanupComponent.
terrainsQuery = SystemAPI.QueryBuilder()
.WithAll<MeshTerrain, MaterialMeshInfo, RenderBounds, LocalToWorld, MeshReference>()
.WithPresent<IsShowingChildren>()
.WithNone<GenerateMesh, GenerateChildren, GenerateCollider, QuadtreeEndNode>()
.Build();
This query executes with no issues, even though there is an ICleanupComponent in the query, the only difference is this one is a managed class. It still behaves like any other ICleanupComponent though, in the sense that it’s still present on the entity after the entity is destroyed, so I can destroy the mesh.
I prefer how the managed object behaves in this instance because I can still use the data that the object contains while the entity is alive. If I convert HeightMap to an ICleanupComponent and leave it as an unmanaged struct then I wouldn’t be able to query for the data it contains until the entity is destroyed. This is a bit cumbersome and converting HeightMap to be a managed class so it functions similar to MeshReference is not an option as HeightMap is used in several bursted jobs it cannot be managed.
Is there some logical reason why unmanaged ICleanupComponents behave so differently from managed ones? How can I get them to behave more similarly without a bunch of hacks? I’d rather not copy the data into an ICleanupComponent on deletion if I can help it.