In 0.2 I see the concise Entities.ForEach is shaping to be the “default” The problem I usually have is that ForEach is a data transformation. It is only able to work on itself or from-to any other components on itself.
Concretely I would like to have a different write target that I can bring to ForEach while maintaining concise syntax while maintaining dependency chain.
For example in this task I want the code to say “for each” component Value, read its value and add them up to summation value in component Collected that is on an another singleton entity. This work do not need to be parallel addition into a single target, it just need to be on thread and add each one in sequentially. Practical use case such as UI that looks to gather data from Entity in the world to cache and display it.
Here’s how it would be concisely, but however cannot be burst compiled or cannot be on thread.
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var singleton = GetSingletonEntity<Collected>();
Entities.ForEach((in Value a) =>
{
Collected b = EntityManager.GetComponentData<Collected>(singleton);
b.summation += a.value;
EntityManager.SetComponentData<Collected>(singleton, b);
}).WithoutBurst().Run();
return default;
}
If I want it to be on thread, burst compiled, ForEach, and not breaking the dependency chain, it would have to be something like capturing the archetype chunk array into the ForEach so the modification go into the database “live”. With ToComponentDataArray (which seems to be a bit cleaner), the copy back step will have to be done right after the job.
EntityQuery singletonQuery;
protected override void OnCreate()
{
base.OnCreate();
singletonQuery = GetEntityQuery(ComponentType.ReadOnly<Collected>());
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var acctB = GetArchetypeChunkComponentType<Collected>(isReadOnly: false);
var aca = singletonQuery.CreateArchetypeChunkArray(Allocator.TempJob);
var jobHandle = Entities.ForEach((in Value a) =>
{
var na = aca[0].GetNativeArray(acctB);
var previousData = na[0];
previousData.summation += a.value;
na[0] = previousData;
}).Schedule(inputDeps);
return jobHandle;
}
Is it possible to currently code something shorter like (made-up code) :
EntityQuery singletonQuery;
protected override void OnCreate()
{
base.OnCreate();
singletonQuery = GetEntityQuery(ComponentType.ReadOnly<Collected>());
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var jobHandle = Entities.ForEach((in Value a) =>
{
var previousData = cda[0];
previousData.summation += a.value;
cda[0] = previousData;
}).WithComponentDataArray(singletonQuery, out var cda, isReadOnly: false).Schedule(inputDeps);
return jobHandle;
}
So I can have any additional linearized array of data inside ForEach generated from any other unrelated query that is writable, and the job knows how to tie it into its job handle.
*test file with 2 passed test about 2 approaches above
5229482–521528–ECSTheoryTest.cs (3.5 KB)