(编辑:见下面我的编辑)
为了在使用 ECS 时减少样板,我将这段代码变成:
前:
public class MySystem : JobComponentSystem
{
public struct Group
{
// A long list of different ComponentDataArray
// Eg.
public ComponentDataArray<Position> Positions;
public int Length;
}
[Inject] private Group _Group;
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
MyJob job = new Job()
{
DeltaTime = Time.deltaTime,
// That same long list of ComponentDataArray
};
return job.Schedule(_Group.Positions.Length, 64, inputDeps);
}
[BurstCompile]
struct MyJob : IJobParallelFor
{
public float DeltaTime;
// That same long list of ComponentDataArray AGAIN.
public void Execute(int i)
{
// MyJob code
}
}
}
后:
public class MySystem : JobComponentSystem
{
public struct Group
{
// A long list of different ComponentDataArray
// Eg.
public ComponentDataArray<Position> Positions;
public int Length;
}
[Inject] private Group _Group;
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
MyJob job = new Job()
{
DeltaTime = Time.deltaTime,
Group = _Group
};
return job.Schedule(_Group.Positions.Length, 64, inputDeps);
}
[BurstCompile]
struct MyJob : IJobParallelFor
{
public float DeltaTime;
public Group Group;
public void Execute(int i)
{
// MyJob code
}
}
}
在那之前,一切正常。直到我尝试在每个实体初始化后为其添加一个组件。
public class MySystem: JobComponentSystem
{
public struct Group
{
// A long list of different ComponentDataArray
// Eg.
public ComponentDataArray<Position> Positions;
public SubtractiveComponent<Initialized> Initialized;
public int Length;
public EntityArray Entities;
}
[Inject] private Group _Group;
public class EntityBarrier : BarrierSystem { }
[Inject] private EntityBarrier _EntityBarrier;
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
MyJob job = new MyJob()
{
DeltaTime = Time.deltaTime,
Group = _Group,
CommandBuffer = _EntityBarrier.CreateCommandBuffer()
};
return job.Schedule(_Group.Positions.Length, 64, inputDeps);
}
[BurstCompile]
struct MyJob : IJobParallelFor
{
public float DeltaTime;
public Group Group;
[ReadOnly] public EntityCommandBuffer CommandBuffer;
public void Execute(int i)
{
CommandBuffer.AddComponent(Group.Entities[i], new Initialized());
// MyJob code
}
}
}
它提出了:
InvalidOperationException:NativeArray MyJob.Group.Entities 必须在作业 MySystem:MyJob 中标记为 [ReadOnly],因为容器本身标记为只读。
但是,如果我确实将其更改为[ReadOnly]
,它会抱怨我在到达该行时对其进行了编辑CommandBuffer.AddComponent
。
还有哪个容器提到被标记ReadOnly
?
是否有另一种方法可以将EntityArray
(或向 index 的实体添加组件i
)提供给作业,而不需要示例 1 中的所有样板代码?
编辑:如果我像这样手动喂它,仍然会抱怨:
public class MySystem : JobComponentSystem
{
public struct Group
{
// A long list of different ComponentDataArray
// Eg.
public ComponentDataArray<Position> Positions;
public SubtractiveComponent<Initialized> Initialized;
public int Length;
public EntityArray Entities;
}
[Inject] private Group _Group;
public class EntityBarrier : BarrierSystem { }
[Inject] private EntityBarrier _EntityBarrier;
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
MyJob job = new Job()
{
DeltaTime = Time.deltaTime,
Entities = _Group.Entities,
CommandBuffer = _EntityBarrier.CreateCommandBuffer(),
// That same long list of ComponentDataArray
};
return job.Schedule(_Group.Positions.Length, 64, inputDeps);
}
[BurstCompile]
struct MyJob : IJobParallelFor
{
public float DeltaTime;
public EntityArray Entities;
// That same long list of ComponentDataArray AGAIN.
public void Execute(int i)
{
CommandBuffer.AddComponent(Entities[i], new Initialized());
// MyJob code
}
}
}
这不就是我们应该做的吗?在这里完成:https ://forum.unity.com/threads/some-beginner-questions-about-pure-ecs.524700/#post-3449277
EDIT2:我在他的代码中发现的唯一区别是
[ReadOnly]public EntityArray Entities;
public EntityCommandBuffer CommandBuffer;
并使用EndFrameBarrier
. 我升级了我的代码,但收到:
InvalidOperationException:MyJob.CommandBuffer 未在 IJobParallelFor 作业中声明为 [ReadOnly]。容器不支持并行写入。请使用更合适的容器类型。
因此,为什么我把它ReadOnly
放在首位。