Hello ecs fans, I work on my first unity ecs (1.0) project and this is the issue I struggle with at the moment.
I have units which have UI nameplates. Upon destroying unit entity, nameplate is disabled.
In my current implementation system destroys entities along with disabling nameplate in monobehaviour world and then it destroys the rest of entities which are tagged with DestroyTag.
Problem in my implementation is that the unit entity is destroyed in both queries. So destroy entity is called twice.
I guess it’s problem of the buffer? That it’s playback changes but in second query the changes are still not updated?
I tried to resolve this in jobs but could not figure out how.
In general, if your entity state is based on data structure (see tags) - its more efficient (both code & performance wise) to use operations on queries directly. Same applies to AddComponent[ForEntityQuery], RemoveComponent[ForEntityQuery], etc. In 1.0 there are respective AddComponent & RemoveComponent overloads.
Haven’t notice that it is possible to use an EntityQuery as a parameter for a buffer. Learned something new. Thanks!
I updated code. Though I haven’t managed to store ECBSystem in OnCreate. I tried to use “older” way to get system from World, but now it returns SystemHandle which does not have CreateCommandBuffer method. And if try to use APISystem.GetSingleton… I got exception on play that there must exist 1 system.
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[RequireMatchingQueriesForUpdate]
public partial class DestroySystem : SystemBase
{
private EntityQuery _query;
protected override void OnCreate()
{
base.OnCreate();
_query= new EntityQueryBuilder(Allocator.Temp).WithAll<DestroyTag>().Build(this);
}
protected override void OnUpdate()
{
var ecb = SystemAPI.GetSingleton<EndFixedStepSimulationEntityCommandBufferSystem.Singleton>().CreateCommandBuffer(World.Unmanaged);
Entities.ForEach((DestroyUnitAspect aspect) =>
{
NamePlateManager.Instance.EntityDestroyed(aspect.Entity);
}).WithoutBurst().Run();
ecb.DestroyEntity(_query);
}
}
SystemHandle can be used to obtain an actual system via World.Unmanaged.GetUnsafeSystemRef(handle);
However, that is for unmanaged systems.
EndFixedStepSimulationEntityCommandBufferSystem is a managed system. (or at least was as of 1.0.0-pre15);
To grab it, use World.GetExistingSystemManaged(). It returns actual SystemBase.
ECBSystems are always created with automatic bootstrap, so no need to check if they exist.
If its not an ECBSystem, or something you didn’t declared & created via bootstrap, then its better to use World.GetOrCreateSystemManaged(). Though its a tiny bit slower.