Search Unity

What caused the “changed” status of a chunk to be reset?

Discussion in 'Entity Component System' started by PublicEnumE, Nov 7, 2019.

  1. PublicEnumE

    PublicEnumE

    Joined:
    Feb 3, 2019
    Posts:
    729
    ...and can they be reset manually?

    Specifically, I’m referring to the ‘changed’ values for each component type which would cause a chunk to show up in a EntityQuery with a change filter.

    Are these values only reset once, at the end of the ESC loop?

    Can they be reset manually, by us?

    As a use case, imagine you wanted to capture all chunks which had been changed at an early point in your loop. Then later in your loop, you wanted to capture all chunks which had been changed since the first time you checked.

    (This is not a real example, and there may be better ways to accomplish this specific case with different logic. But I’m wondering if a manual reset is possible).

    Thank you for any help!
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
  3. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,705
    Related to this can you explain to me why DynamicBuffer<TilesBufferComponent> tileBuffer = TileBuffer[e]; trigger a change when it read only ?



    Code (CSharp):
    1.  
    2.         [BurstCompile]
    3.         struct GetMeshTrianglePositions : IJobForEach_BC<TriangleBufferComponent, TileBufferReferneceComponent>
    4.         {
    5.  
    6.             [WriteOnly] public NativeArray<Vector3> MeshTrianglePositions;
    7.             [ReadOnly] public BufferFromEntity<TilesBufferComponent> TileBuffer;
    8.  
    9.  
    10.             public void Execute([ReadOnly] DynamicBuffer<TriangleBufferComponent> t, [ReadOnly] ref TileBufferReferneceComponent c)
    11.             {
    12.                 DebugInfo();
    13.                 Entity e = c.TileBufferEntity;
    14.                 DynamicBuffer<TilesBufferComponent> tileBuffer = TileBuffer[e];  //// THIS CAUSES A CHANGE BUT WHY
    15.                  .....
    16.             }
    17.  
    18.             [BurstDiscard]
    19.             private void DebugInfo()
    20.             {
    21.                 Debug.Log("<b> <size=13> <color=#EA70A3>Info: PlanetCreateMeshSystem : GetMeshTrianglePositions.</color> </size> </b>");
    22.             }
    23.         }
    24.  
    25.  
    Code (CSharp):
    1.  
    2.             var meshTrianglePositions = new NativeArray<Vector3>(triangleCount[0]*3, Allocator.TempJob);
    3.  
    4.             inputDeps = new GetMeshTrianglePositions()
    5.             {
    6.                 MeshTrianglePositions = meshTrianglePositions,
    7.                 TileBuffer = GetBufferFromEntity<TilesBufferComponent>(true)
    8.  
    9.  
    10.             }.ScheduleSingle(qTrianglesBuffer, inputDeps);
    11. [code]
     
  4. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Are you sure it's this system triggering it?

    What other jobs/system are you accessing TilesBufferComponent
     
  5. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,705
    I have other Jobs assessing the buffer but those system only run again for the second time if I use DynamicBuffer<TilesBufferComponent> tileBuffer = TileBuffer[e]; . If I comment it out the system only runs once.

    Here is the job

    Code (CSharp):
    1.  
    2.  
    3.         struct SetTiles : IJobForEach_B<TilesBufferComponent>
    4.         {
    5.  
    6.             public EntityCommandBuffer.Concurrent ecb;
    7.             [DeallocateOnJobCompletion]
    8.             public NativeArray<Entity> eTiles;
    9.  
    10.  
    11.             public void Execute([ReadOnly] DynamicBuffer<TilesBufferComponent> b)
    12.             {
    13.                 DebugInfo();
    14.  
    15.                 for (int i = 0; i < b.Length; i++)
    16.                 {
    17.  
    18.                     Entity e = eTiles[i];
    19.  
    20.                     ecb.SetComponent<TilePositionComponents>(i, e, new TilePositionComponents
    21.                     {
    22.                         Position = new float3(b[i].PositionX,
    23.                                                b[i].PositionY,
    24.                                                b[i].PositionZ)
    25.                     });
    26.  
    27.                 }
    28.             }
    29.  
    30.             [BurstDiscard]
    31.             private void DebugInfo()
    32.             {
    33.                 Debug.Log("<b> <size=13> <color=#A2E721>Info : PlanetSetTileDataSystem : SetTiles 1.</color> </size> </b>");
    34.             }
    35.         }
    36.  
    Code (CSharp):
    1.  
    2. ..
    3.             inputDeps = new SetTiles()
    4.             {
    5.                 ecb = ecbs.CreateCommandBuffer().ToConcurrent(),
    6.                 eTiles = qTiles.ToEntityArray(Allocator.TempJob)
    7.  
    8.             }.ScheduleSingle( qTileBuffer, inputDeps);
    9. ..
    10.  
    11.  
    12.  
    Code (CSharp):
    1.  
    2. ..
    3. qTileBuffer.SetFilterChanged(typeof(TilesBufferComponent));
    4. ..
    5.  
     
  6. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,705
    Here is what i seen when I comment it out

    Screen Shot 2019-11-07 at 10.14.58 PM.png
    Vs not

    Screen Shot 2019-11-07 at 10.16.18 PM.png

    both the last two systems implement IJobForEach_B<TilesBufferComponent>. DynamicBuffer<TilesBufferComponent> tileBuffer = TileBuffer[e]; is in PlanetCreateMeshSystem : GetMeshTrianglePositions[/QUOTE]
     
  7. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    How is your EntityQuery (qTileBuffer??!!??) looks like?
    It should declare TilesBufferComponent as readonly too.
     
  8. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,705
    Its read only but setfilter is just typeof, i dont have Unity in front of me atm but should SetFilter be read only ?
    Code (CSharp):
    1.  
    2.  
    3.  qTileBuffer = GetEntityQuery(ComponentType.ReadOnly < TilesBufferComponent>());
    4.  
    5. // but ..
    6. qTileBuffer.SetFilterChanged(typeof(TilesBufferComponent));
    7.  
    8.  
     
  9. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    SetFilterChanged doesn't care about read/write permissions as far as i know.
    Anyway after looking at your code it work as expected.
    Where are you invoking qTileBuffer.SetFilterChanged(typeof(TilesBufferComponent)); ? It should be on the system update method before everything.
     
  10. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    Ok. Now i see what you mean and it seems that when you access a BufferFromEntity it will always be accessed as RW no matter what. Hence your data will be marked as changed just from accessing it this way.
    If you look at BufferFromEntity source code you can see a remark about it:
    Code (CSharp):
    1.         public DynamicBuffer<T> this[Entity entity]
    2.         {
    3.             get
    4.             {
    5. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    6.                 // Note that this check is only for the lookup table into the entity manager
    7.                 // The native array performs the actual read only / write only checks
    8.                 AtomicSafetyHandle.CheckReadAndThrow(m_Safety0);
    9.  
    10.                 m_EntityComponentStore->AssertEntityHasComponent(entity, m_TypeIndex);
    11. #endif
    12.  
    13.                 // TODO(dep): We don't really have a way to mark the native array as read only.
    14.                 BufferHeader* header = (BufferHeader*) m_EntityComponentStore->GetComponentDataWithTypeRW(entity, m_TypeIndex, m_GlobalSystemVersion, ref m_TypeLookupCache);
    15.  
    16. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    17.                 return new DynamicBuffer<T>(header, m_Safety0, m_ArrayInvalidationSafety, m_IsReadOnly, m_InternalCapacity);
    18. #else
    19.                 return new DynamicBuffer<T>(header, m_InternalCapacity);
    20. #endif
    21.             }
    22.         }
    I would suggest you to rethink the way your access that data.
     
  11. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,705
    OK thanks for digging into this ....
     
  12. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,705
    Are there any obvious drawbacks if I just deleted the entity with the buffers. The mesh build system is not intended to updated per frame