Search Unity

Race condition with ExportDynamicBodiesJob when simply wanting to read all Translations

Discussion in 'Entity Component System' started by MrDos1, Jan 29, 2021.

  1. MrDos1

    MrDos1

    Joined:
    Dec 14, 2016
    Posts:
    20
    Hello everyone!

    I have a very simple ComponentSystem from which I would like to only read all Translations from a query. Query will be more complex than just Translation, but for easy reproduction, I'm using the simplest query possible.

    I don't have any errors with Entities.ForEach, but I want to iterate through my Translations on the main thread and NOT in parallel. While SystemBase offers the WithoutBurst() + Run() combo, it clearly DOES run in parallel anyway, which is strange... Another question for another thread, unless you've got a comment on that.

    Anyway, here is my component system.

    Code (CSharp):
    1. public class DebugReadingTranslation : ComponentSystem
    2.     {
    3.         private EntityQuery entityQuery;
    4.  
    5.  
    6.         protected override void OnCreate()
    7.         {
    8.             entityQuery = EntityManager.CreateEntityQuery(ComponentType.ReadWrite<Translation>());
    9.         }
    10.  
    11.         protected override void OnUpdate()
    12.         {
    13.             NativeArray<ArchetypeChunk> archetypeChunkArray = entityQuery.CreateArchetypeChunkArray(Allocator.Temp);
    14.  
    15.             for (int chunkIndex = 0; chunkIndex < archetypeChunkArray.Length; chunkIndex++)
    16.             {
    17.                 ArchetypeChunk chunk = archetypeChunkArray[chunkIndex];
    18.                 NativeArray<Entity> entities = chunk.GetNativeArray(EntityManager.GetEntityTypeHandle());
    19.                 NativeArray<Translation> translations = chunk.GetNativeArray(EntityManager.GetComponentTypeHandle<Translation>(true));
    20.  
    21.                 for (int entityIndex = 0; entityIndex < entities.Length; entityIndex++)
    22.                 {
    23.                     Entity entity = entities[entityIndex];
    24.                     Translation translation = translations[entityIndex];
    25.  
    26.                     // Simply read the translation
    27.                 }
    28.             }
    29.         }
    30.     }
    31.  
    With the code above, I get the following error:

    InvalidOperationException: The previously scheduled job ExportPhysicsWorld:ExportDynamicBodiesJob writes to the ComponentTypeHandle<Unity.Transforms.Translation> ExportDynamicBodiesJob.JobData.PositionType. You must call JobHandle.Complete() on the job ExportPhysicsWorld:ExportDynamicBodiesJob, before you can read from the ComponentTypeHandle<Unity.Transforms.Translation> safely.


    I understand what it means. Basically the physics thread is still writing to the translations so I can't yet read them. Either this error is not the actual problem, or else I'm very confused. It sounds wrong to ask the physics thread to finish from the main thread half way through the frame...

    So I'm very curious. How does ForEach ensure the physics thread is done before giving me my Translations?
    I simply want to read them.

    Let me know what you think or if this sounds like a bug I should report! Not sure.

    Versions:
    OS: Windows 10
    Unity: 2020.2.1f1
    Entities: Version 0.17.0-preview.41
    Havok: Version 0.6.0-preview.3
    Jobs: Version 0.8.0-preview.23
    Unity Physics: Version 0.6.0-preview.3