Create a cleanup component
To create a cleanup component, create a struct that inherits from ICleanupComponentData
. Make sure to add it to entities at runtime, because cleanup components cannot be baked.
The following code sample shows an empty cleanup component:
public struct ExampleCleanupComponent : ICleanupComponentData
{
}
Note
Empty cleanup components are often sufficient, but you can add properties to store information required to cleanup the target archetypes.
Perform cleanup
You can use cleanup components to help you manage entities that require cleanup when destroyed. Unity prevents you from destroying an entity that contains a cleanup component.
When you try to destroy an entity with an attached cleanup component, Unity removes all non-cleanup components instead. The entity still exists until you remove all cleanup components from it.
To perform cleanup for entities of a specific archetype:
- Create a new tag component and add the tag component to the archetype.
- Create a new cleanup component that contains information required to clean up a certain entity archetype.
- Create a system that:
- Gets newly created entities of the target archetype. These are entities that contain the tag component but not the cleanup component.
- Adds the cleanup component to these entities.
- Create a system to handle the cleanup component removal:
- In OnUpdate, handle entities which need cleanup at runtime:
- Get the entities that have been provisionally destroyed and require cleanup. These are entities that contain the cleanup component, but not the tag component.
- Perform the appropriate cleanup work for the entities.
- Remove the relevant cleanup component(s) from the entities.
- In OnDestroy, handle entities which need cleanup at shutdown:
- Get all entities with the cleanup component, including those that still have the tag component.
- Perform the appropriate cleanup work for the entities.
- Remove the relevant cleanup component(s) from the entities.
- In OnUpdate, handle entities which need cleanup at runtime:
Example system which adds the cleanup component:
public partial struct AddCleanupSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
var ecb = new EntityCommandBuffer(state.WorldUpdateAllocator);
foreach (var (tag, entity) in SystemAPI.Query<ExampleTagComponent>().WithEntityAccess())
{
// Add the cleanup component to all entities with the tag component.
ecb.AddComponent<ExampleCleanupComponent>(entity);
}
ecb.Playback(state.EntityManager);
ecb.Dispose();
state.Enabled = false;
}
}
Example system which destroys entities that have the tag component:
[UpdateAfter(typeof(AddCleanupSystem))]
public partial struct DestructionSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
var ecb = new EntityCommandBuffer(state.WorldUpdateAllocator);
foreach (var (tag, entity) in SystemAPI.Query<ExampleTagComponent>().WithAll<ExampleCleanupComponent>().WithEntityAccess())
{
// Destroy the Entity, which means all components, except for the cleanup component, gets removed.
ecb.DestroyEntity(entity);
}
ecb.Playback(state.EntityManager);
ecb.Dispose();
state.Enabled = false;
}
}
Example system which removes the cleanup component:
[UpdateAfter(typeof(DestructionSystem))]
public partial struct CleanupSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
var ecb = new EntityCommandBuffer(state.WorldUpdateAllocator);
foreach (var (cleanup, entity) in SystemAPI.Query<ExampleCleanupComponent>().WithNone<ExampleTagComponent>().WithEntityAccess())
{
// Perform cleanup ...
// Remove Cleanup Component. This triggers the destruction of the Entity.
ecb.RemoveComponent<ExampleCleanupComponent>(entity);
}
ecb.Playback(state.EntityManager);
ecb.Dispose();
state.Enabled = false;
}
}