EntityQuery with Enableable Component not working correctly in Job?

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;

namespace TEST
{
    [BurstCompile]
    public partial struct DestroyByTimeSystem : ISystem
    {
        private EntityQuery m_Query;

        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            var builder = new EntityQueryBuilder(Allocator.Temp)
               .WithAll<DestroyAbleTag, AliveTag, DestroyByTimeComp>();
            m_Query = state.GetEntityQuery(builder);
        }

        [BurstCompile]
        public void OnDestroy(ref SystemState state)
        {
        }

        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
          
            var ecbSingleton = SystemAPI.GetSingleton<BeginSimulationEntityCommandBufferSystem.Singleton>();
            var ecb = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter();
            var destroyByTimeJob = new DestroyByTimeJob
            {
                Commanbuffer = ecb,
                DeltaTime = SystemAPI.Time.DeltaTime,
            };
            destroyByTimeJob.ScheduleParallel(m_Query);
        }
    }

    [BurstCompile]
    public partial struct DestroyByTimeJob : IJobEntity
    {
        [ReadOnly] public float DeltaTime;
        public EntityCommandBuffer.ParallelWriter Commanbuffer;

        public void Execute([EntityIndexInChunk] int index, Entity entity, ref DestroyByTimeComp destroyByTimeComp)
        {
            if (destroyByTimeComp.TimeToDestroy > 0)
            {
                destroyByTimeComp.TimeToDestroy -= DeltaTime;
                return;
            }
            //UnityEngine.Debug.LogError("SetComponentEnabled");
            Commanbuffer.SetComponentEnabled<AliveTag>(index, entity, false);
        }
    }
}

when time run out of an entity AliveTag will disable.
OnUpdate menthor if i log out CalculateEntityCount it will not count that entity
but the Job still execute through that entity.
anyone know why?

If you finish job right now and debug.log entities count or will check their component enable state it wouldn’t change, as you’re using EntityCommandBuffer for changing enabled state, it will change on ECB playback, before that their state will be unchanged, if you want enable\disable component immediately in job - use ComponentLookup.SetComponentEnabled or use ArchetypeChunk.SetComponentEnabled (if you’re in IJobChunk)

3 Likes

thanks for the answer eizenhorn.
Component is completely disable after ECB playback. i was check it with log and on hirachy as well. But Job still Execute after that ECB playback (next frame and so on).
if i put AliveTag into Execute param it will not run through (is what i doing now) But it should run fine with Query

Well, first of all - make sure you not enable it anywhere (or not create new entities). As it definitely works as intended (see below). I create 10 entities, job iterates through them, disable component (exactly 10 times) and that’s it. It’s not running anymore (technically job schedules and do enable bits check, but it wouldn’t call Execute).

public struct AliveTag : IComponentData, IEnableableComponent {}

    public struct DestroyByTimeComp : IComponentData
    {
        public float TimeToDestroy;
    }
  
    [BurstCompile]
    public partial struct DestroyByTimeSystem : ISystem
    {
        private EntityQuery m_Query;
        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            var types = new NativeArray<ComponentType>(2, Allocator.Temp)
            {
                [0] = ComponentType.ReadOnly<AliveTag>(),
                [1] = ComponentType.ReadWrite<DestroyByTimeComp>(),
            };
            state.EntityManager.CreateEntity(state.EntityManager.CreateArchetype(types), 10);
          
            var builder = new EntityQueryBuilder(Allocator.Temp)
               .WithAll<AliveTag, DestroyByTimeComp>();
            m_Query = state.GetEntityQuery(builder);
        }
        [BurstCompile]
        public void OnDestroy(ref SystemState state)
        {
        }
        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
       
            var ecbSingleton = SystemAPI.GetSingleton<BeginSimulationEntityCommandBufferSystem.Singleton>();
            var ecb = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter();
            var destroyByTimeJob = new DestroyByTimeJob
            {
                Commanbuffer = ecb,
                DeltaTime = SystemAPI.Time.DeltaTime,
            };
            destroyByTimeJob.ScheduleParallel(m_Query);
        }
    }
[BurstCompile]
public partial struct DestroyByTimeJob : IJobEntity
{
    [ReadOnly] public float DeltaTime;
    public EntityCommandBuffer.ParallelWriter Commanbuffer;

    public void Execute([EntityIndexInChunk] int index, Entity entity, ref DestroyByTimeComp destroyByTimeComp)
    {
        Debug.Log("Process entity");
        if (destroyByTimeComp.TimeToDestroy >= 0)
        {
            destroyByTimeComp.TimeToDestroy -= DeltaTime;
            return;
        }
        Debug.Log("Disable component");
        Commanbuffer.SetComponentEnabled<AliveTag>(index, entity, false);
    }
}
    }

1 Like