[request] Include An Ijobforeachwithentity Interface With No Icomponentdata Type Parameters

Say I wanted to use a job to add a component data to entities with a component tag. You can use an IJobParallelFor with a NativeArray of Entities you want to operate on and an entity command buffer:
AddComponentJobParallelFor

struct AddIntComponents : IJobParallelFor
{
    public EntityCommandBuffer.Concurrent Ecb;
    public NativeArray<Entities> Entities;

    public void Execute(int i)
    {
        Ecb.AddComponent(i, entities[i], new MyInt { Value = 0f });
    }
}

Or you can use an IJobForEachWithEntity with the tag component as a type parameter:
AddComponentJobForEachWithEntity<>

struct AddIntComponents : IJobForEachWithEntity<MyComponentTag>
{
    public EntityCommandBuffer.Concurrent Ecb;

    public void Execute(Entity e, int i, ref MyComponentTag tag)
    {
        Ecb.AddComponent(i, e, new MyInt { Value = 0f });
    }
}

Since the tag component isn’t read from or written to, I believe a version of IJobForEachWithEntity with no type parameters would be more convenient and performant than the above options, as shown here:
AddComponentJobForEachWithEntity

[RequireComponentTag(typeof(MyComponentTag))]
struct AddIntComponents : IJobForEachWithEntity
{
    public EntityCommandBuffer.Concurrent Ecb;
 
    public void Execute(Entity e, int i)
    {
        Ecb.AddComponent(i, e, new MyInt { Value = 0f });
    }
}

Are there any plans for offering this option?

1 Like

Use IJobChunk and create an EntityQuery for your required types

public class MySystem : JobComponentSystem {

        struct Job : IJobChunk {
            [ReadOnly] public ArchetypeChunkEntityType entityType;
            public EntityCommandBuffer.Concurrent CommandBuffer;
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) {
                for (int i = 0; i < chunk.Count; i++) {
                   var entities = chunk.GetNativeArray(entityType);
                    for (int j = 0; j < entities.Length; j++) {
                        CommandBuffer.AddComponent(chunkIndex, entities[j], new MyComponent());
                    }
                }
            }
        }

        private SomeBarriere EndFrameBarrier;
        protected override void OnCreateManager() {
            base.OnCreateManager();
            EndFrameBarrier = World.GetOrCreateManager<SomeBarriere>();
            myQuery = GetEntityQuery(ComponentType.ReadOnly<MyTag>());
        }

        protected override JobHandle OnUpdate(JobHandle inputDeps) {

            var job = new Job() {
                CommandBuffer = EndFrameBarrier.CreateCommandBuffer().ToConcurent(),
                entityType = GetArchetypeChunkEntityType(),
            };
            return job.Schedule(myQuery, inputDeps);

        }
    }
2 Likes

I’d love to have this as well, got few systems that only require component tags and entity array access

1 Like

All places I required this in the past were replaced with the batch Add/RemoveComponent APIs of EntityManager which is much faster and even less code. You only have to make sure not to introduce additional barriers, eg by putting the CS doing it right before/after the already existing barrier.

There still could be other use cases eg using ComponentDataFromEntity but I currently don’t require this.

I appreciate your quick reply, but you have a LOT of boiler plate code in your above example. I’m mainly making this request for the sake of convenience.

Thanks for your contribution. This solves a part of my problem. Perhaps my presented use case wasn’t the best one to use for this request, as many of my jobs that would benefit from my request do use conditional logic (as you considered above) or don’t even use entity command buffers.

1 Like

+1 Would be nice to have

this article really helped clear up the batching vs adding something to a command to have it done later
https://gametorrahod.com/batched-operation-on-entitymanager/