List/Array data in IComponentData

I am working through an implementation of A* path finding using DOTS and am coming stuck.

The basic idea so far is that anything that wants to find a path creates a PathRequest IComponent that gets processed by a JobComponentSystem, calculating the path and returning the path way-points. Entities with PathRequest come into a IJobForEachWithEntity like below:

public struct AStarJob : IJobForEachWithEntity<PathRequest>
{
            // calculate path
}

Where I am coming stuck is returning an array of way-points. My initial thought was to create a list in the PathRequest with a bool to indicate whether the path has been found:

public struct PathRequest : IComponentData
{
    public int startIndex;
    public int endIndex;
    public bool pathComplete;
    public NativeList<int> path;
}

but I am unable to use the NativeList type in an IComponentData. Is the only way I can return individual arrays of way-points by using unsafe code with fixed arrays?
Any other ideas?

DynamicBuffer for mutable data arrays.

I set up a dynamic buffer and passed the BufferFromEntity to the job:

public struct AStarJob : IJobForEachWithEntity<PathRequest>
    {
        // ...
        public BufferFromEntity<PathCompleteBuffer> pathCompleteBuffer;

        public void Execute(Entity entity, int index, ref PathRequest p)
        {
            // ...
        }
}
}

I’m now getting an error:
Error validOperationException: AStarJob.Data.pathCompleteBuffer is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.

which I understand, but looking through what other people have used in the past leads me to think I should use IJobProcessComponentDataWithEntity except that its now deprecated to use IJobForEachWithEntity So the only job option i have is parallel and therefore cannot use dynamic buffers?

When you schedule a IJobForEach job, you have the choice between parallelism (job.Schedule(…)) and single-threaded (job.ScheduleSingle(…)).
If you still want parallelism and you are sure there is no race condition, you can add the attribute [NativeDisableParallelForRestriction] to your buffer variable ‘pathCompleteBuffer’.

1 Like

I’m not sure if that is the case but if your buffer is in the same entity of PathRequest you can use IJobForEachWithEntity with DynamicBuffers → IJobForEachWithEntity_EBC<T0, T1>
```csharp
** public struct AStarJob : IJobForEachWithEntity_EBC<PathCompleteBuffer, PathRequest> {

  public void Execute(Entity entity, int index, DynamicBuffer<PathCompleteBuffer> buffer, ref PathRequest p) {
    // ...
  }
}**

```

1 Like

This worked a treat, I can easily pull in buffer types and write to them in the job (not sure if this is parallel or not though).

IJobForEach is parallel

I found that currently the best solution for working around this is to implement your own collections based on only memory allocated via UnsafeUtility.Malloc since you can stick these into components. Its a bit of work but currently i have most common collections implemented