Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Why there is no DidChange method in BufferFromEntity<T>?

Discussion in 'Entity Component System' started by YurySedyakin, Apr 30, 2020.

  1. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    61
    I see ComponentDataFromEntity<T> has DidChange() but BufferFromEntity<T> doesn't. Does anybody know a specific reason for this? Also I noticed that ArchetypeChunk has DidChange<T>() will happily accept T derived from IBufferElementData, but this doesn't help in the situations where I have to use BufferFromEntity, i.e. where I am reaching to another entity's buffer.
    Any advice on how I can change-check dynamic buffers?
     
  2. cort_of_unity

    cort_of_unity

    Unity Technologies

    Joined:
    Aug 15, 2018
    Posts:
    97
    No reason, we probably just forgot to add it in both places. Good catch, I'll take care of that right now!
     
    YurySedyakin likes this.
  3. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    61
    For those interested, this has been addressed in v.0.12.0, thank you @cort_of_unity!
     
  4. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    61
    Just noticed something - even though DidChange() was added to dynamic buffers, WithChangeFilter() still doesn't work properly with dynamic buffers, in my case it basically reports as always changed
     
  5. msfredb7

    msfredb7

    Joined:
    Nov 1, 2012
    Posts:
    143
    If I'm not mistaken, that's because getting a buffer (even in ReadOnly) always marks it as a Read/Write. Not sure if it's a bug or a technical limitation I don't understand.

    I modified the Entities package for one of my projects and added a true GetBufferReadOnly method. It seems to work fine at the moment.
     
    YurySedyakin likes this.
  6. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    61
    Thank you @msfredb7. Can you share the code for the true read only buffer access method?
     
  7. msfredb7

    msfredb7

    Joined:
    Nov 1, 2012
    Posts:
    143
    From the Git diff, I think that's all the changes related to my GetReadOnlyBuffer:

    NB:
    - My changes were done based on Entities 0.10.0, so they might not work out of the box for higher versions.
    - This might very well expose bugs as I haven't tested all use cases
    - Remember that this is not code officially supported by Unity. I suggest you rely on it as little as possible.

    Unity.Entities/EntityManagerAccessComponentData.cs, line 305
    Code (CSharp):
    1. // ADDED BY FBESSETTE 2020-04-09
    2. public DynamicBuffer<T> GetBufferReadOnly<T>(Entity entity) where T : struct, IBufferElementData
    3. {
    4.     var typeIndex = TypeManager.GetTypeIndex<T>();
    5.     var ecs = GetCheckedReadEntityDataAccess();
    6.  
    7. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    8.     var safetyHandles = &ecs->DependencyManager->Safety;
    9. #endif
    10.  
    11.     return ecs->GetBufferReadOnly<T>(entity
    12. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    13.         , safetyHandles->GetSafetyHandle(typeIndex, true),
    14.         safetyHandles->GetBufferSafetyHandle(typeIndex)
    15. #endif
    16.     );
    17. }
    18.  
    Unity.Entities/EntityManager.cs, line 73
    Code (CSharp):
    1. // ADDED BY FBESSETTE 2020-05-24
    2. internal EntityDataAccess* GetCheckedReadEntityDataAccess()
    3. {
    4. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    5.     AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
    6.     if (m_JobMode != m_EntityDataAccess->m_JobMode)
    7.     {
    8.         throw new InvalidOperationException($"EntityManager cannot be used from this context job mode {m_JobMode} != current mode {m_EntityDataAccess->m_JobMode}");
    9.     }
    10. #endif
    11.     return m_EntityDataAccess;
    12. }
    Unity.Entities/ExclusiveEntityTransaction.cs, line 133
    Code (CSharp):
    1. // added by fbessette 2020-04-19
    2. public DynamicBuffer<T> GetBufferReadOnly<T>(Entity entity) where T : struct, IBufferElementData
    3. {
    4.     return m_Manager.GetBufferReadOnly<T>(entity);
    5. }
    Unity.Entities/EntityDataAccess.cs, line 877
    Code (CSharp):
    1. // ADDED BY FBESSETTE 2020-04-19
    2. public DynamicBuffer<T> GetBufferReadOnly<T>(Entity entity
    3. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    4.     , AtomicSafetyHandle safety, AtomicSafetyHandle arrayInvalidationSafety
    5. #endif
    6.     ) where T : struct, IBufferElementData
    7. {
    8.     var typeIndex = TypeManager.GetTypeIndex<T>();
    9.  
    10. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    11.     EntityComponentStore->AssertEntityHasComponent(entity, typeIndex);
    12.     if (!TypeManager.IsBuffer(typeIndex))
    13.         throw new ArgumentException(
    14.             $"GetBuffer<{typeof(T)}> may not be IComponentData or ISharedComponentData; currently {TypeManager.GetTypeInfo<T>().Category}");
    15. #endif
    16.  
    17.     if (IsMainThread)
    18.         DependencyManager->CompleteReadAndWriteDependency(typeIndex);
    19.  
    20.     BufferHeader* header =
    21.             (BufferHeader*)EntityComponentStore->GetComponentDataWithTypeRO(entity, typeIndex);
    22.  
    23.     int internalCapacity = TypeManager.GetTypeInfo(typeIndex).BufferCapacity;
    24.  
    25. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    26.     var useMemoryInit = EntityComponentStore->useMemoryInitPattern != 0;
    27.     byte memoryInitPattern = EntityComponentStore->memoryInitPattern;
    28.     return new DynamicBuffer<T>(header, safety, arrayInvalidationSafety, true, useMemoryInit, memoryInitPattern, internalCapacity);
    29. #else
    30.     return new DynamicBuffer<T>(header, internalCapacity);
    31. #endif
    32. }
     
    Last edited: Jul 27, 2020
  8. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    61
    Thanks @msfredb7. I do realize this is not officially maintained code, I'm just stuck with my dynamic buffers constantly becoming overwritten (without this actually happening). In my case this leads to meshes being rebuilt every frame :(