如何将实体传递给作业以添加组件?
How to pass Entities to a job to add Components?
(编辑: 请参阅下面我的编辑)
为了在使用 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: The NativeArray MyJob.Group.Entities must be marked [ReadOnly] in the job MySystem:MyJob, because the container itself is marked read only.
但是如果我将其更改为 [ReadOnly]
,它会在到达行 CommandBuffer.AddComponent
.
时抱怨我编辑它
还提到哪个容器被标记为 ReadOnly
?
是否有另一种方法可以将 EntityArray
(或将组件添加到索引 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 is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.
因此我把它放在第一位的原因是 ReadOnly
。
我找到了一种方法,但我不确定它是否安全或是否可行但是:
// In your job
[NativeDisableParallelForRestriction] public EntityCommandBuffer CommandBuffer;
无论您是使用 EndFrameBarrier
还是自己继承。 (我真的不知道有什么区别)
(编辑: 请参阅下面我的编辑)
为了在使用 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: The NativeArray MyJob.Group.Entities must be marked [ReadOnly] in the job MySystem:MyJob, because the container itself is marked read only.
但是如果我将其更改为 [ReadOnly]
,它会在到达行 CommandBuffer.AddComponent
.
还提到哪个容器被标记为 ReadOnly
?
是否有另一种方法可以将 EntityArray
(或将组件添加到索引 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 is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.
因此我把它放在第一位的原因是 ReadOnly
。
我找到了一种方法,但我不确定它是否安全或是否可行但是:
// In your job
[NativeDisableParallelForRestriction] public EntityCommandBuffer CommandBuffer;
无论您是使用 EndFrameBarrier
还是自己继承。 (我真的不知道有什么区别)