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

Question How do I query for a DynamicBuffer in idiomatic foreach? DOTS 1.0

Discussion in 'Entity Component System' started by sirwhatevers, Oct 6, 2022.

  1. sirwhatevers

    sirwhatevers

    Joined:
    Aug 25, 2017
    Posts:
    33
    Sorry if this is a dumb question, but I can't seem to figure out how to query for a dynamic buffer. Is it possible yet with idiomatic foreach?
     
  2. DaxodeUnity

    DaxodeUnity

    Unity Technologies

    Joined:
    Aug 5, 2021
    Posts:
    27
    It indeed is, simply:
    Code (CSharp):
    1. foreach (var elements in SystemAPI.Query<DynamicBuffer<MyElement>>()){
    2.     foreach (var element in elements) {
    3.         Debug.Log(element);
    4.     }
    5. }
     
    Nams33 likes this.
  3. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,029
    Is there any performance difference using for loop vs foreach to loop elements of dynamic buffer at both SystemBase and ISystem?
     
  4. sirwhatevers

    sirwhatevers

    Joined:
    Aug 25, 2017
    Posts:
    33
    Ah okay, this worked, thank you. The mistake I was making was trying to use RefRO<DynamicBuffer<...>>. So, are DynamicBuffers always queried as RW or RO?
     
  5. DaxodeUnity

    DaxodeUnity

    Unity Technologies

    Joined:
    Aug 5, 2021
    Posts:
    27
    RefRO and RefRW are struct : IComponentData only.

    Managed comps, dynamic buffers, aspects etc. are simply typed directly.

    So a buffer queried is always accessed as RW.
     
    Last edited: Oct 8, 2022
    WAYNGames likes this.
  6. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    939
    This is something I have notice is missing in the tutorial/guide unity provides. There is no use of dynamic buffer.

    I based my DOTS training tutorial on a tower defence game and use a dynamic buffer of waypoints to define the path of the entities.

    That way I have all the basic components.
    Aspects with transform aspect.
    ReadOnly with the speed component.
    ReadWrite with the tracking id the current/next path index component.
    And dynamic buffer for the waypoints.

    I figured how to use the dynamic buffer but I was not sure about the access pattern so thanks for clarifying it.
     
  7. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    939
    Does that mean that if I want ReadOnly access to a dynamic buffer I have to use IJobEntity ? or Entites.ForeEach ?
     
  8. DaxodeUnity

    DaxodeUnity

    Unity Technologies

    Joined:
    Aug 5, 2021
    Posts:
    27
    Not nesscarirly, tho it is a great way! There are two other ways if you want to still type it directly.
    The simplest one is this:
    Code (CSharp):
    1. public void OnUpdate(ref SystemState state) {
    2.   var myElementsLookup = SystemAPI.GetBufferLookup<MyElement>(true);
    3.   foreach (var (entity, myComp) in Query<RefRO<MyComp>>().WithAll<MyElement>().WithEntityAccess()) {
    4.     var myElements = myElementsLookup[entity];
    5.     foreach (var element in myElements){
    6.       Debug.Log(element);
    7.     }
    8.   }
    9. }
    or the more preferred in this case (as to not do a lookup):
    Code (CSharp):
    1. BufferTypeHandle<MyElements> myElementsHandle;
    2. public void OnCreate(ref SystemState state){
    3.   myElementsHandle = GetBufferTypeHandle<MyBufferElement>(true);
    4. }
    5. public void OnUpdate(ref SystemState state){
    6.   myElementsHandle.Update(ref state);
    7.   var myQuery = SystemAPI.QueryBuilder().WithAll<MyElement>().Build();
    8.   var chunks = myQuery.ToArchetypeChunkArray(WorldUpdateAllocator);
    9.   foreach (var chunk in chunks) {
    10.     var myElementsLookup = chunk.GetBufferAccessor(myElementsHandle);
    11.     var entityCount = chunk.Count;
    12.     for (int i = 0; i < entityCount; i++) {
    13.       var myElements = myElementsLookup [i];
    14.       foreach (var element in myElements) {
    15.         Debug.Log(element);
    16.       }
    17.     }
    18.   }
    19. }
    In anycase, we're aware and will look at better ways to do this in the future! :)
     
    Last edited: Oct 9, 2022
    lclemens and WAYNGames like this.
  9. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    Perhaps we should have a DynamicBuffer.ReadOnly type like with NativeArray for querying dynamic buffers we only want to read from.
     
    lclemens and DaxodeUnity like this.