Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

NativeList Paraller write

Discussion in 'Entity Component System' started by mati2762, Dec 31, 2021.

  1. mati2762

    mati2762

    Joined:
    Dec 26, 2017
    Posts:
    27
    I don't know how add element to native list in parallel jobs.

    this is exmaple my code:
    Code (CSharp):
    1.    
    2. NativeList<FXEffect>.ParallelWriter effects = new NativeList<FXEffect>(Allocator.TempJob).AsParallelWriter();
    3. Entities.ForEach((Entity entity, int entityInQueryIndex, ref Translation trans) => {
    4.  
    5.          // How to add element to effects variable
    6.  
    7.             }).ScheduleParallel();
    8. effects.Dispose();
    9.  
    I need only add elements to the list

    I spent a lot of time and i don't know how this issue resolve.
    Please help.
     
    Last edited: Jan 1, 2022
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    You need to set a capacity for the list before the job.

    But if you are adding lots of elements, you don't want to use a NativeList. You want to use something like NativeStream instead.
     
    Antypodish likes this.
  3. mati2762

    mati2762

    Joined:
    Dec 26, 2017
    Posts:
    27

    NativeStream effects = new NativeStream(1, Allocator.TempJob);


    var ps = effects.AsWriter();
    Entities.ForEach((Entity entity, int entityInQueryIndex, ref Translation trans) => {


    ps.BeginForEachIndex(0);
    ps.Write<FXEffect>(new FXEffect(example, example));
    ps.EndForEachIndex();


    }).ScheduleParallel();

    Job.WithCode(() => {
    Debug.Log(effects.AsReader().Count());
    effects.Dispose();
    }).WithoutBurst().Run();


    Could you add example code ?

    I get error like this:

    Index {0} is out of restricted IJobParallelFor range [{1}...{2}] in NativeStream.
     
  4. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    This is how I do it but it's using IJobEntityBatch:
    Code (CSharp):
    1. // We need the query so we can get the count
    2. private EntityQuery query;
    3.  
    4. protected override void OnCreate() {
    5.     base.OnCreate();
    6.  
    7.     // This is based from your example
    8.     // Compose the query with the right components here
    9.     this.query = GetEntityQuery(typeof(Translation));
    10. }
    11.  
    12. protected override void OnUpdate() {
    13.     NativeList<FxEffect> effects =
    14.         new NativeList<FxEffect>(this.query.CalculateEntityCount(), Allocator.TempJob);
    15.  
    16.     // Schedule job
    17.     PopulateEffectsListJob job = new PopulateEffectsListJob() {
    18.         entityType = GetEntityTypeHandle(),
    19.         translationType = GetComponentTypeHandle<Translation>(),
    20.         resultList = effects.AsParallelWriter()
    21.     };
    22.     this.Dependency = job.ScheduleParallel(this.query, 1, this.Dependency);
    23.  
    24.     // Don't forget to dispose
    25.     this.Dependency = effects.Dispose(this.Dependency);
    26. }
    27.  
    28. private struct PopulateEffectsListJob : IJobEntityBatchWithIndex {
    29.     [ReadOnly]
    30.     public EntityTypeHandle entityType;
    31.  
    32.     [ReadOnly]
    33.     public ComponentTypeHandle<Translation> translationType;
    34.  
    35.     public NativeList<FxEffect>.ParallelWriter resultList;
    36.  
    37.     public void Execute(ArchetypeChunk batchInChunk, int batchIndex, int indexOfFirstEntityInQuery) {
    38.         NativeArray<Entity> entities = batchInChunk.GetNativeArray(this.entityType);
    39.         NativeArray<Translation> translations = batchInChunk.GetNativeArray(this.translationType);
    40.  
    41.         for (int i = 0; i < batchInChunk.Count; i++) {
    42.             Entity entity = entities[i];
    43.             Translation translation = translations[i];
    44.          
    45.             // Add FxEffect here
    46.             this.resultList.AddNoResize(new FxEffect(... whatever));
    47.         }
    48.     }
    49. }
    The caveat is this adds an FxEffect for every entity in your query. If this is not what you wanted, you can use some kind of a custom null struct value equivalent of FxEffect for those entities that should not have an FxEffect. We use our custom Option<T> for this.
     
    Last edited: Jan 1, 2022