Search Unity

[solved ]entityManger 2 systems conflict. (BufferFromEntity & ComponentDataFromEntity)

Discussion in 'Entity Component System' started by Antypodish, Sep 8, 2018.

  1. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    Jump to post #8 for resolution, based on BufferFromEntity & ComponentDataFromEntity


    Edited original title: BufferArray access between 2 systems conflict.

    I have two systems with Jobs, which access same BufferArray, while updating values respectively.
    I understand that BufferArray should not be accessed by other systems / jobs at same time.
    Hence I try to prevent that, but failing so far.

    I tried implement [UpdateAfter ( typeof ( BarrierA ) ) ] and [UpdateAfter ( typeof ( BarrierB ) ) ] at header of each script, but that don't e seams resolve issue in this case, while I receive conflict error:

    InvalidOperationException: The native container has been declared as [WriteOnly] in the job, but you are reading from it.

    BufferArray array is not declared explicitly [WriteOnly] in any job. But by accessing it in two jobs, appears to call that error.

    Any thoughts?

    Full error.
    InvalidOperationException: The native container has been declared as [WriteOnly] in the job, but you are reading from it.
    Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrowNoEarlyOut (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) <0x369ab9c0 + 0x00052> in <f718fbf7147e402282fdacf37bdd8584>:0
    Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at C:/buildslave/unity/build/Runtime/Export/AtomicSafetyHandle.bindings.cs:143)
    Unity.Entities.ComponentJobSafetyManager.CompleteWriteDependency (System.Int32 type) (at C:/Users/.../AppData/Local/Unity/cache/packages/packages.unity.com/com.unity.entities@0.0.12-preview.11/Unity.Entities/ComponentJobManager.cs:273)
    Unity.Entities.EntityManager.GetComponentData[T] (Unity.Entities.Entity entity) (at C:/Users/.../AppData/Local/Unity/cache/packages/packages.unity.com/com.unity.entities@0.0.12-preview.11/Unity.Entities/EntityManager.cs:471)
    ECS.Blocks.CompositePatternSystem+MovePatternDataJob.Execute () (at Assets/Project/Scripts/Blocks/Composites/MoveCompositePatternSystem.cs:170)
    Unity.Jobs.IJobExtensions+JobStruct`1[T].Execute (T& data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at C:/buildslave/unity/build/Runtime/Jobs/Managed/IJob.cs:30)
     
    Last edited: Sep 9, 2018
  2. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    You shouldn't have to care about this at all. InputDeps of second system should automatically contain the job(s) of the first system. Does deactivating one system really remove this error?
     
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    I have added Disable component tag. First to system A then swapped and added to system B.
    Each systemruns ok, as long both are not running.

    These systems are very basics. But maybe there is something else happening.

    Edit:
    In fact I double checked now and error leads to different point of a system A, where error is called. Still related to the topic.

    I use entityManager in IJob to fetch data from entity, since I can not use commandBuffer to get such data. Is it right way?

    I got something like that in the IJob.
    Code (CSharp):
    1.  
    2. // a_entityBuffer is a BufferArray
    3. Common.BufferElements.EntityBuffer entityBuffer = movePatternData.a_entityBuffer [i][i_bufferIndex] ;
    4.  
    5. Blocks.CompositeComponent compositeComponent = entityManager.GetComponentData <Blocks.CompositeComponent> ( entityBuffer.entity ) ;
    But this is illegal, because of enttiyBuffer, where error points (line 3)

    The native container has been declared as [WriteOnly] in the job, but you are reading from it.
     
  4. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    As far as I know using the EntityManager directly prevents automatic dependency management as the system is no longer able to track what is accessed.

    Why don't you use BufferFromEntity?
     
    Antypodish likes this.
  5. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    Yep, I suspected something in this context. I wanted avoid EntityManager in Jobs.

    I will look into it. I thought I may be able to avoid storing additional type of data. Not a big deal.
    But yes that maybe a solution, which should eliminate EntityManager in a Job all together.

    Thx
     
  6. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    BufferFromEntity doesn't store anything, it's only an interface to the actual chunk data.
    I didn't look into it in detail but I'm pretty sure it's doing the same thing you are doing only that dependencies and safety checks are active.
     
  7. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    Ok figured out right way I believe, to replace entityManger.GetComponentData in IJob

    Instead of using suggested
    BufferFromEntity
    I use
    ComponentDataFromEntity
    This gives me exactly what I need.

    But @julian-moschuering definatelly did put me on right track. Thx again.


    BufferFromEntity requires
    Code (CSharp):
    1. public struct myElement: IBufferElementData
    Which wasn't suitable for me in this case

    While ComponentDataFromEntity operates well with
    Code (CSharp):
    1. public struct myComponent : IComponentData
    In both cases I access data with an entity, however in first case is the array of elements data
    I needed as per second case, access component data, without array iteration, adding, or appending.

    ComponentDataFromEntity requires injection in a system
    Code (CSharp):
    1. [Inject] private ComponentDataFromEntity <MyComponent> myComponents;
    Then passing through the job handle as other group data for example.
    And to access in the IJob itself,
    Code (CSharp):
    1. MyComponent myComponent = myComponents [jobEntity] ;
    Where

    BufferFromEntity appears that can be passed into the job handle directly (but is likely it need first get added elements)
    Code (CSharp):
    1. MyBufferElement myBufferElements = GetBufferArrayFromEntity <MyBufferElement> (false),
    Then in job can be accessed with
    Code (CSharp):
    1. MyBufferElement myBufferElement = myBufferElements [jobEntity] [elementIndex] ;

    Usefull references from github

    ComponentDataFromEntity
    Unity-Technologies/EntityComponentSystemSamples
    https://github.com/Unity-Technologi...FromEntity&unscoped_q=ComponentDataFromEntity

    BufferFromEntity
    Unity-Technologies/EntityComponentSystemSamples
    https://github.com/Unity-Technologies/EntityComponentSystemSamples/search?utf8=✓&q=BufferDataFromEntity&type=


    And forum
    How can I improve or jobify this system? ( Building a list )
    https://forum.unity.com/threads/how...s-system-building-a-list.547324/#post-3614833
     
    Last edited: Oct 3, 2018
  9. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    Great!

    Oh, your initial post mentioned BufferArray to be the problem, which would require BufferFtomEntity.
     
  10. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    Well yes.
    This at least what has been triggering the error.
    But now we know solution and I believe correct way of doing thing.