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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Foreign Entities inside foreach / Access buffer from another entities (solved)

Discussion in 'Entity Component System' started by GameMadeByGamers, Apr 8, 2020.

  1. GameMadeByGamers

    GameMadeByGamers

    Joined:
    Nov 25, 2014
    Posts:
    54
    Hi, Here a bit of context , am trying to compare 2 paths of node(Int) between two entities and wanted to know how i could acces DynamicBuffer/Component of a foreign entities inside the foreach lamba or job.

    A. Is there already a known way to access data from a foreign entities in foreach?
    B. Do im bound to use EntityManager.GetBuffer and run the job on the maintread?
    C. Do I need to further divide the work through multiple job/systems?

    PS : i know that my code currently produce aliasing with the lookup. Will try to replace this with a entityquery.

    (pastebin link : https://pastebin.com/DdwpnwZC)
    Code (CSharp):
    1.  
    2.     protected override void OnUpdate()
    3.     {
    4.  
    5.         EntityCommandBuffer.Concurrent ecb = endSimulationEcbSystem.CreateCommandBuffer().ToConcurrent();
    6.         CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
    7.  
    8.         BufferFromEntity<NodeIDPath> bufferLookup = GetBufferFromEntity<NodeIDPath>();
    9.         ComponentDataFromEntity<UnitsGroup> componentLookup = GetComponentDataFromEntity<UnitsGroup>();
    10.  
    11.         float _castRadius = castRadius;
    12.  
    13.         //Find already existing unitsGroup in proximity of the unit
    14.         JobHandle FindUnitsGroupInProximityJobHandle = Entities
    15.         .ForEach((Entity entity, int entityInQueryIndex
    16.         , ref NeedUnitsGroup needUnitsGroup
    17.         , in OwnerComponent ownerComponent
    18.         , in Translation translation
    19.         , in DynamicBuffer<NodeIDPath> nodePath) =>
    20.         {
    21.             NativeList<int> hitsIndices = new NativeList<int>(Allocator.Temp);
    22.  
    23.             CollisionFilter filter = new CollisionFilter
    24.             {
    25.                 BelongsTo = 3,
    26.                 CollidesWith = 3,
    27.                 GroupIndex = 0
    28.             };
    29.             //Check for nearby unitsgroup already existing
    30.             Aabb aabb = new Aabb
    31.             {
    32.                 Min = translation.Value + new float3(-_castRadius, 0, -_castRadius),
    33.                 Max = translation.Value + new float3(_castRadius, 0, _castRadius)
    34.             };
    35.             OverlapAabbInput overlapAabbInput = new OverlapAabbInput
    36.             {
    37.                 Aabb = aabb,
    38.                 Filter = filter,
    39.             };
    40.             if (collisionWorld.OverlapAabb(overlapAabbInput, ref hitsIndices))
    41.             {
    42.                 //Foreach detected unitsGroup check we compare the unitsGroup node vs the one of the units
    43.                 for (int i = 0; i < hitsIndices.Length; i++)
    44.                 {
    45.                     Entity unitsGroupEntity = collisionWorld.Bodies[hitsIndices[i]].Entity;
    46.                     //check if of the same owner
    47.                     if (componentLookup[unitsGroupEntity].owner != ownerComponent.owner)
    48.                     {
    49.                         continue;
    50.                     }
    51.                     //Compare the nodePath with the one units
    52.                     DynamicBuffer<NodeIDPath> unitsGroupNodesPath = bufferLookup[unitsGroupEntity];
    53.                     //Check if the nodepath are equal if yes we can stop here , we found a corresponding group
    54.                     if (unitsGroupNodesPath.Equals(nodePath))
    55.                     {
    56.                         needUnitsGroup.foundUnitsGroupEntity = unitsGroupEntity;
    57.                         break;
    58.                     }
    59.                     //Check if the second node is different, if yes , this unitsgroup is not valid for the current unit
    60.                     if (unitsGroupNodesPath[1] != nodePath[1] || unitsGroupNodesPath.Length <= 2 ||        nodePath.Length <= 2)
    61.                     {
    62.                         continue;
    63.                     }
    64.                     //Finally we will check if the current unit can follow the group for part of the path and separate later
    65.                     //Take the shorter one to loop trough both and see if they have part of path in common
    66.                     int loopLength = unitsGroupNodesPath.Length;
    67.                     if (nodePath.Length < unitsGroupNodesPath.Length)
    68.                     {
    69.                         loopLength = nodePath.Length;
    70.                     }
    71.                     for (int x = 2; x < loopLength; x++)
    72.                     {
    73.                         if (nodePath[x] != unitsGroupNodesPath[x])
    74.                         {
    75.                             needUnitsGroup.foundUnitsGroupEntity = unitsGroupEntity;
    76.                             ecb.AddComponent<UnitsGroupSeparation>(entityInQueryIndex, entity, new UnitsGroupSeparation(x - 1));
    77.                             break;
    78.                         }
    79.                     }
    80.                 }
    81.             }
    82.             hitsIndices.Dispose();
    83.  
    84.             needUnitsGroup.proximityCheck = true;
    85.         }).Schedule(Dependency);
    86.  
    87.  
     
    Last edited: Apr 8, 2020
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,987
    You already have it with ComponentDataFromEntity and BufferFromEntity. Unless your issue is writing to these types inside the lambda. In that case you need to rethink your problem.
     
  3. GameMadeByGamers

    GameMadeByGamers

    Joined:
    Nov 25, 2014
    Posts:
    54
    No , i only need to read the data, but how do i avoid aliasing error in this case?
     
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,987
    Remove the nodePath argument in the lambda and use the lambda's entity field to look up the buffer.
     
  5. GameMadeByGamers

    GameMadeByGamers

    Joined:
    Nov 25, 2014
    Posts:
    54
    Oh i see ... thanks for the help!
     
  6. GameMadeByGamers

    GameMadeByGamers

    Joined:
    Nov 25, 2014
    Posts:
    54
    Just one last thing if you may , in this case it's better to use lookup like i did or i should use entityQuery?
     
  7. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,987
    It is not obvious from your code in what way you would use an EntityQuery instead. Could you elaborate?
     
  8. GameMadeByGamers

    GameMadeByGamers

    Joined:
    Nov 25, 2014
    Posts:
    54
    Sry for the lack of clarity, Im only checking for equality and loop over the shorter path (DynamicBuffer) to see if the two path have part of them in common. I was only asking in term of performance if there's a difference between doing so with "lookup" or "EntityQuery".

    Thanks in advance.
     
  9. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,987
    In what way would you use an EntityQuery instead of BufferFromEntity? What API would you use? EntityQuery is tied to a few different mechanisms with drastically different behavior and implications.