The setup: An Enemy attacks the Player. To effect damage, the Enemy decrements the Player’s health (EnemySystem_ForEach.cs below). I attempted to rewrite this ForEach as an IJobChunk (EnemySystem_IJobChunk.cs below).
Problem: The ForEach writes to both the Enemy and the Player chunks. As a result, I tried to pass the health container* to IJobChunk. However, runtime provides an error that says the container must be marked readonly. *health container being ComponentDataFromEntity.
Question: How do I rewrite ForEach as an IJobChunk, when ForEach is writing to chunks of different archetypes?
Note: This came up after realizing IJobForEach* structs are deprecated. Otherwise, I’d be more than happy to use IJobForEach*.
Note: One possibility is to include both Player and Enemy in the EntityQuery. In Execute, I would then iterate over all queried entities to find the player first, then iterate over all remaining entities, that are enemies. Is this reasonable? (nvm: This wouldn’t work because Enemy and Player have different archetypes, so they wouldn’t live in the same Execute call…)
Note: ECSSamples includes IJobChunk but both exampes as of writing (ex 1, ex 2), afaik, only write to chunks of one archetype at a time.
Original working code EnemySystem_ForEach.cs
public class EnemySystem : SystemBase {
protected override void OnUpdate()
{
var healthGroup = GetComponentDataFromEntity<HealthComponent>();
var player = GetSingletonEntity<PlayerComponent>();
Dependency = Entities.ForEach((
Entity entity,
int entityInQueryIndex,
ref EnemyComponent enemy) =>
{
enemy.AttackCount += 1;
var health = healthGroup[player];
health.Value -= 1;
healthGroup[player] = health;
}.Schedule(Dependency);
}
Attempt at IJobChunk EnemySystem_IJobChunk.cs
public class EnemySystem : SystemBase {
EntityQuery EnemyQuery => GetEntityQuery(typeof(EnemyComponent));
struct DuckSystemJob2 : IJobChunk
{
// breaks down when I add the following line, as it must be readonly
public ComponentDataFromEntity<HealthComponent> HealthGroup;
public ArchetypeChunkComponent<EnemyComponent> EnemyType;
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
{
var chunkEnemies = chunk.GetNativeArray(EnemyType);
for (var i = 0; i < chunk.Count; i++) {
var enemy = chunkEnemies[i];
enemy.AttackCount += 1;
chunkEnemies[i] = enemy;
}
}
}
protected override void OnUpdate() {
Dependency = new EnemySystemJob() {
HealthGroup = GetComponentDataFromEntity<HealthComponent>(),
}.Schedule(EnemyQuery, Dependency);
}
}