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

Resolved Queries what's the mindset now?

Discussion in 'DOTS Dev Blitz Day 2023 - Q&A' started by HBG-Mathieu, Aug 23, 2023.

  1. HBG-Mathieu

    HBG-Mathieu

    Joined:
    Feb 16, 2023
    Posts:
    59
    Hello,

    https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/systems-entityquery-create.html

    So it looks like this is the new recommanded way to create queries. But that doesn't mean that the other ways were removed (like ComponentType[]). Because having a ComponentTypeSet is the only way to add and remove several components ? What's the current mindset about all the possibilities with Queries/ComponentType ?
    I'm not a big fan of having several ways of doing "the same thing" accross the project.

    And about the Queries in foreach statements :
    So we can't really use a premade query instead I guess ? (lot of code needed at least)
    And you always have to have a mandatory component in the query right? So if it's an empty component, isn't that pointless ?

    And by the way, what does happen inside when you use/don't use RefRO and RefRW ? There is the metadata for the sheduler ok (also used in a foreach?) but if you don't use it... is it simply considered as a RefRW ?

    A lot of questions for those little queries, sorry !
    And thanks !
     
    Last edited: Aug 23, 2023
  2. alexk-unity

    alexk-unity

    Unity Technologies

    Joined:
    Mar 28, 2017
    Posts:
    4
    EntityQueryBuilder is the recommended method for creating queries because it's fully Burst-compatible and can be used in Burst-compiled ISystems. ComponentType[] is a managed array and cannot be used in Burst-compiled code, and it generates managed objects that have to be cleaned up by the GC.

    All query APIs now funnel into ultimately using an EntityQueryBuilder, so it's most efficient just to use that API directly.

    Removing all the ComponentType[] APIs prior to the 1.0 release was not feasible and would have broken many user projects, but it's a good idea to move over to using EntityQueryBuilder as the others may be deprecated in the future.
     
    HBG-Mathieu and JesOb like this.
  3. alexk-unity

    alexk-unity

    Unity Technologies

    Joined:
    Mar 28, 2017
    Posts:
    4
    Correct. The short explanation is that the sourcegen for using an idiomatic foreach requires that you use SystemAPI.Query, and the query types must be known at compile time. If you want to use a premade query, you could write an IJobChunk, but that's a bit more code.

    Also correct, Query takes at least one generic argument. For example if you want to iterate over every entity that has a certain empty component, you can use a discard argument, so that you don't accidentally try to access the empty component, which would give an error.

    Code (CSharp):
    1. struct TagComponent : IComponentData {};
    2. struct IntComponent : IComponentData
    3. {
    4.     int Value;
    5. };
    6.  
    7. public void OnUpdate()
    8. {
    9.     // Normally, you'd specify an empty component in WithAll, so that it doesn't
    10.     // require a variable in the tuple
    11.     foreach (var (transform, entity) in
    12.         SystemAPI.Query<LocalTransform>().WithAll<TagComponent>().WithEntityAccess())
    13.     {
    14.         // OK
    15.     }
    16.  
    17.     // If you only want to query an empty component, you can provide it as the
    18.     // generic argument to Query and discard it in the tuple
    19.     foreach (var (_, entity) in SystemAPI.Query<TagComponent>().WithEntityAccess())
    20.     {
    21.         // OK
    22.     }
    23. }

    IComponent access defaults to RefRO, so that you don't inadvertently create a write-dependency when you don't need one.

    From https://docs.unity3d.com/Packages/c...anual/systems-systemapi-query.html#query-data

    Code (CSharp):
    1. float deltaTime = SystemAPI.Time.DeltaTime;
    2.  
    3. foreach (var (transform, speed) in SystemAPI.Query<RefRW<LocalTransform>, RotationSpeed>())
    4.     transform.ValueRW = transform.ValueRO.RotateY(speed.RadiansPerSecond * deltaTime);
     
    HBG-Mathieu likes this.
  4. HBG-Mathieu

    HBG-Mathieu

    Joined:
    Feb 16, 2023
    Posts:
    59
  5. carlos_truong

    carlos_truong

    Joined:
    May 9, 2023
    Posts:
    33
    https://forum.unity.com/threads/systemapi-querys-question.1399153/#post-8801800

    Is it right?
     
    HBG-Mathieu likes this.
  6. alexk-unity

    alexk-unity

    Unity Technologies

    Joined:
    Mar 28, 2017
    Posts:
    4
    Yes, that's correct. Using RefRO avoids the copy and also provides safety against trying to write to the component.

    Omitting RefRO use value semantics. It will give you a copy of the component. You can modify the copy, but it won't be written back to the chunk data.

    Either way, the component dependency will be registered as read-only and only complete write jobs for the component before running the body of the foreach.
     
    carlos_truong and HBG-Mathieu like this.