(Sorry for the inconvenience, My english is poor, the following content is translated by AI)
I am currently working with Unity DOTS, and I have encountered an issue as follows:
Error: InvalidOperationException: The previously scheduled job DestroyJob writes to the Unity.Entities.EntityCommandBuffer DestroyJob.JobData.ECB. You must call JobHandle.Complete() on the job DestroyJob, before you can write to the Unity.Entities.EntityCommandBuffer safely.
The functionality of the code is simple, it first destroys all planes (Entities with the TagPlane component), and then recreates some new planes.
DestroyJob.cs
namespace Systems.Jobs
{
[BurstCompile]
public partial struct DestroyJob : IJobEntity
{
public EntityCommandBuffer.ParallelWriter ECB;
[BurstCompile]
public void Execute(in TagPlane tag, in Entity entity)
{
ECB.DestroyEntity(entity.Index, entity);
}
}
}
SpawnJob.cs
namespace Systems.Jobs
{
public partial struct SpawnJob : IJobEntity
{
public EntityCommandBuffer.ParallelWriter ECB;
public void Execute([ChunkIndexInQuery] int chunkIndex, SpawnerAspect spawnerAspect)
{
for (int i = 0; i < SpawnerAspect.SpawnerComponent.ValueRO.NumberToSpawn; i++)
{
var spawnerComponent = SpawnerAspect.SpawnerComponent.ValueRO;
var plane = ECB.Instantiate(chunkIndex, spawnerComponent.Prefab);
var localTransform = new LocalTransform
{
Position = // randomPosition,
Rotation = quaternion.identity,
Scale = 0.1f
};
ECB.SetComponent(chunkIndex, plane, localTransform);
ECB.AddComponent(chunkIndex, plane, new TagPlane());
}
}
}
}
SpawnerSystem.cs
public void OnUpdate(ref SystemState state){
var singleton = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>();
var ecb = singleton.CreateCommandBuffer(state.WorldUnmanaged);
new DestroyJob()
{
ECB = ecb.AsParallelWriter()
}.Schedule();
// state.Dependency.Complete(); this works
new SpawnJob()
{
ECB = ecb.AsParallelWriter(),
}.Schedule();
}
I tried adding state.Dependency.Complete()
before new SpawnJob
, and the issue was resolved, as the error no longer occurs. However, I am unsure if Complete()
is a blocking operation, and I feel that this is not the optimal solution.
I have searched for some information, but I am not sure if it is correct:
-
I am unable to obtain an instance of
SystemBase
(EndSimulationEntityCommandBufferSystem
) within anISystem
, and thus cannot call theAddJobHandleForProducer
method. Additionally, some discussions mentioned thatSingleton
already handles dependencies by Unity, so there is no need to callAddJobHandleForProducer
. Therefore, I do not believe this is the cause of the issue. -
Some suggest manually specifying the dependencies of the Job. After modifying the code as follows, the issue remains unresolved:
var destroyJob = new DestroyJob() { ECB = ecb.AsParallelWriter() }.Schedule(state.Dependency); // destroyJob.Complete(); without this line, cause same error var spawnJob = new SpawnJob() { ECB = ecb.AsParallelWriter(), }.Schedule(destroyJob); state.Dependency = spawnJob;
I am now seeking to understand how to use the EntityCommandBuffer
in multiple IJobEntity
within an ISystem
. Although state.Dependency.Complete()
can resolve the issue, I consider it a temporary solution.
Many thanks!