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 Get a NativeArray of a query

Discussion in 'Entity Component System' started by Saeed-B, Jun 17, 2023.

  1. Saeed-B

    Saeed-B

    Joined:
    Jul 12, 2021
    Posts:
    46
    Hi,
    I have a architecture where there are some Units components, they have Ally or Enemy tags attached to their entities (self explanatory). now, if I want to make each Unit to go towards the closest Unit with the opposite tag, I need a list of all it's enemies, right? to do that, I'm planning to pass some sort of
    NativeArray<Unit>
    and
    NativeArray<LocalTransform>
    to the IJob that's handling the logic, but I don't know how to convert a Query like
    SystemAPI.Query<RefRO<LocalTransform>, RefRO<UnitComponentData>>()
    to value tuple and then down to two
    NativeArrays
    . Is this even possible? is this the best approach?

    P.S. How to convert
    SystemAPI.Query<RefRO<LocalTransform>, RefRO<UnitComponentData>>()
    into two variables of
    NativeArray<RefRO<LocalTransform>>
    and
    NativeArray<RefRO<UnitComponentData>>
    ?

    Thanks!
     
  2. FaithlessOne

    FaithlessOne

    Joined:
    Jun 19, 2017
    Posts:
    256
    You can use an EntityQuery instance and call ToComponentDataArray<T>() two times to get the component data and process it in a separate job:
    But there are also other approaches to get the closest unit of a certain type. For example when each unit category (ally/enemy) is placed on its own layer and using Physics sphere collision to determine the other opposing units. Someone here in the forums said that Physics is really fast doing such stuff with the right collision filters, but I don't testet it. API for example would be:
     
    Last edited: Jun 17, 2023
    Saeed-B likes this.
  3. Saeed-B

    Saeed-B

    Joined:
    Jul 12, 2021
    Posts:
    46
    Thanks! will try both!
     
  4. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,292
    Usually you'd use some kind of spatial partitioning structure, like a QuadTree or an Octree to speed up the process and avoid O(N) * O(N) operations. There are free options, but they're not updated to recent Unity's editor versions, e.g. https://github.com/marijnz/NativeOctree. Though if you remove editor related code it should work just fine (I'm still using fork of it with minimum changes). People also use basic spatial partitioning by hash + positions, but its kinda unscalable solution as project grows.

    Insert all required entities into spatial structure lookup, grab that lookup for the system, "query" into it and you should get your nearby entities. Physics does the same thing under the hood, except more complicated and optimized for, well, physics rather than triggers or detection. Using Unity.Physics should work as well.

    In any case, to access query you can use EntityQuery.ToComponentDataArray[Async].
    To access other entities by Entity - use ComponentLookup or BufferLookup.
     
  5. Saeed-B

    Saeed-B

    Joined:
    Jul 12, 2021
    Posts:
    46
    thanks. yes partitioning is a must, and although the repo sounds solid, I prefer to do my own implementation. besides, the repo is a bit old too, and it'd be a good practice anyway!

    + I used the
    EntityQuery.ToComponentDataArray
    (not async) for now since that won't be the bottleneck anyway. so far so good. That part is executing lightning fast even when the query has ~2k results