Search Unity

Lambda ForEach subtractive components?

Discussion in 'Entity Component System' started by thelebaron, Jan 23, 2019.

  1. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
    Is there a way to use subtractive components with the Lambda function, or is there a way to use the lambda ForEach with a specific ComponentGroup?

    Also could we get further clarification on what is going away? I think I read ComponentArray and ComponentDataArray might going away but I'm unsure how to handle subtractive queries besides chunk iteration(which I guess I shouldve learned by now). The ECS github docs talk about injection going away and "IJobProcessComponentData, chunk iteration, ForEach, and (Job)ComponentSystem.GetComponentGroup" staying but where does that leave getting arrays from component groups?
     
  2. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    138
    You can pass a ComponentGroup as the last parameter of the ForEach:
    Code (CSharp):
    1. ForEach((Entity entity, ref MyComponentData mdc) => {
    2. // Code
    3. }, m_MyGroup);
     
    thelebaron likes this.
  3. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
    Much appreciated. Also I just saw the best practices page so that also clears up my other questions.
     
  4. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    451
    Were is best practice page? I can't find it.
     
  5. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
  6. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    451
  7. timmehhhhhhh

    timmehhhhhhh

    Joined:
    Sep 10, 2013
    Posts:
    157
    is it no longer possible to use ComponentGroup (or, it seems 'EntityQuery' now) with ForEach? if not, how do we now do more complex reactive groups?

    EDIT 1: i see now we can use these with 'With()'

    is it possible to completely in-line the whole thing, ie, for more complex reactive groups using subtractive queries? something like:

    Code (CSharp):
    1.  
    2. Entities
    3.     .WithAll<Initialized>()
    4.     .WithAny<ComponentType.Subtractive(typeof(RequiredType1), ComponentType.Subtractive(typeof(RequiredType2), ComponentType.Subtractive(typeof(RequiredType3)>()
    5. .ForEach((Entity entity) =>
    6. {
    7.     PostUpdateCommands.RemoveComponent<Initialized>(entity);
    8. });
    EDIT 2:
    it seems 'EntityQueryDesc cannot contain Exclude Component types' (it would be nice if we could somehow get a compile time error for this...). but is there any other (nice) way to get at what i'm trying here, which is to 'give me all the entities which have been initialized as part of this group but now are missing any one of these components'?
     
    Last edited: May 18, 2019
  8. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    .WithNone<> is a thing.
     
  9. timmehhhhhhh

    timmehhhhhhh

    Joined:
    Sep 10, 2013
    Posts:
    157
    i want the OR version of this, Any<> but with subtractive components
     
  10. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    It is already the "OR/Any" version (if any of the defined types exists then the query will not match).
     
  11. timmehhhhhhh

    timmehhhhhhh

    Joined:
    Sep 10, 2013
    Posts:
    157
    i still don't grok. maybe a fuller code example will help (this is just going off the top of my head, so there may be typos):

    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine;
    3.  
    4. public class TestReactiveSystem : ComponentSystem
    5. {
    6.     struct Initialized : ISystemStateComponentData { };
    7.  
    8.     EntityQuery removedTesters;
    9.  
    10.     protected override void OnCreate()
    11.     {
    12.         base.OnCreate();
    13.  
    14.         var removedQuery = new EntityQueryDesc
    15.         {
    16.             Any = new ComponentType[] { ComponentType.Exclude(typeof(TestComponent1)), ComponentType.Exclude(typeof(TestComponent2)), },
    17.         };
    18.         removedTesters = GetEntityQuery(removedQuery);
    19.     }
    20.  
    21.     protected override void OnUpdate()
    22.     {
    23.         Entities
    24.             .WithAll<TestComponent1, TestComponent2>()
    25.             .WithNone<Initialized>()
    26.             .ForEach((Entity entity) =>
    27.         {
    28.             PostUpdateCommands.AddComponent(entity, new Initialized());
    29.             Debug.Log("THIS WORKS. ADDING " + entity.Index);
    30.         });
    31.        
    32.         Entities
    33.             .WithAll<Initialized>()
    34.             .WithNone<TestComponent1, TestComponent2>()
    35.         .ForEach((Entity entity) =>
    36.         {
    37.             PostUpdateCommands.RemoveComponent<Initialized>(entity);
    38.             Debug.Log("THIS DOESN'T WORK, YOU'LL NEVER SEE ME REMOVING " + entity.Index);
    39.         });
    40.  
    41.         Entities
    42.             .WithAll<Initialized>()
    43.             .With(removedTesters)
    44.         .ForEach((Entity entity) =>
    45.         {
    46.             PostUpdateCommands.RemoveComponent<Initialized>(entity);
    47.             Debug.Log("THIS WORKS. REMOVING " + entity.Index);
    48.         });
    49.     }
    50. }
    51.  
    52. public class TestComponent1Proxy : ComponentDataProxy<TestComponent1> { }
    53. public struct TestComponent1 : IComponentData { }
    54.  
    55. public class TestComponent2Proxy : ComponentDataProxy<TestComponent2> { }
    56. public struct TestComponent2 : IComponentData { }
    57.  
    split out the TestComponents so you can attach them to a gameobject. add both and a GameObjectEntity. run the scene, and disable the components one at a time. you should see the message that's part of the loop with the 'removedTesters' query, but not the other one. at least, that's what i was seeing before i posted my edits and last responses (maybe i mucked something up along the way).
     
  12. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    Okay I see what you are trying to do. Yeah, you cannot use
    ComponentType.Exclude
    in
    EntityQueryDesc
    . It'll throw exception.

    And
    .WithNone
    won't help you because it does
    ((A || B) -> not match)
    or
    ((!A && !B) -> match)
    which is different from what you want:
    ((!A || !B) -> match)
    .

    You'll need 2 separate queries for your scenario.