Search Unity

How to run query over same component in parallel?

Discussion in 'Entity Component System' started by Cell-i-Zenit, Jan 18, 2020.

  1. Cell-i-Zenit

    Cell-i-Zenit

    Joined:
    Mar 11, 2016
    Posts:
    290
    Hi,

    I have a flag component (seasoncolor) and depending on this flag and ANOTHER component i want to do different things.

    Flag + ComponentA = DoXXX();

    Flag + ComponentB = DoYYY();

    Flag + ComponentC = DoZZZ();

    Code (CSharp):
    1. var handle1 = Entities
    2.                 .WithBurst()
    3.                 .WithNone<Plane>()
    4.                 .ForEach((ref SeasonColor seasonColor, in LerpData lerpData) =>
    5.                 {
    6.                         seasonColor.Value = colortA;
    7.                 })
    8.                 .Schedule(inputDeps);
    9.  
    10.             var handle2 = Entities
    11.                 .WithBurst()
    12.                 .WithAll<Plane>()
    13.                 .ForEach((ref SeasonColor seasonColor) =>
    14.                 {
    15.                     seasonColor.Value = colorB;
    16.                 })
    17.                 .Schedule(inputDeps);
    Here you can see that i want to assign colorB to all entities with a plane component and colorA to all entities with lerpdata attached ..

    The error is telling me that i write to SeasonColor two times ...

    Is there a way to prevent this error from happening? Thanks
     
  2. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    handle2 must have handle1 as a dependency, since it write to the same type of component
     
  3. Cell-i-Zenit

    Cell-i-Zenit

    Joined:
    Mar 11, 2016
    Posts:
    290
    I know that this is a workaround, but this shouldnt be needed as a Plane cannot have lerpdata
     
  4. Lucas-Meijer

    Lucas-Meijer

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    175
    This logic is best expressed with a. ijobChunk job, that checks the optional component per chunk and based on that does one or the other loop.

    Ijobchunk syntax is a lot more verbose than entities.foreach, which is something we have on our radar to improve.

    bye, Lucas
     
  5. Gen_Scorpius

    Gen_Scorpius

    Joined:
    Nov 2, 2016
    Posts:
    65
    For what purposes or reasons would I use IJobChunk over entities.foreach?

    I plan on creating my own ECS physics character controller implementation based on the one of the sample repository which uses archetypechunk syntax. However, I thought of using entities.foreach since it is more concise.
     
  6. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    992
    If your logic is totaly different then you should porbably do several systems.(or entiteis.foreach)
    If most of your logic is shared, then using the IJobChunk like sugested by unity team is a good fit.
    You'll write the sahred logic just once and the specifics can be handles within the same job, meaning you get the thread safety.

    For exemple (probably a bad one), you may want your character controller to move the entity through physics if it has physicsvelocity component and use through translation otherwise. that is the spécific part but the fact that your character has a speed, a direction, maybe a ground check, that is common. so instead of writing these in 2 systems, you may do it just once, inssuring consistency and maintainability of your code without losing performance.
     
  7. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,779
    For example, you can sum up total taken damage of each entity, per each chunk. Store summed damage per chunk, it in Native Array, which is size of number of chunks.

    Then in second chained job, singlethreaded, you just iterate through that native array of taken damage sums, to calculate final total sum of taken damage.

    You have typically much fewer chunks to work on, than number of entities. So running secondary job is fast.
     
  8. Lucas-Meijer

    Lucas-Meijer

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    175
    @Gen_Scorpius we tend to use IJobChunk a lot for situations exactly like yours. when you want to write to a certain component, but what you write to it depends on which other components there are. If you do this with Entities.ForEach, you'll have to all schedule them in serial, because they all write to the same component, and our safety system doesn't have the kind of granularity to see that "oh, but one of them uses .WithNone<Plane>() and the other one is .With<Plane>() so this combo is actually safe".

    You can see a lot of our usage of IJobChunk in Unity.Transforms. we basically loop over all chunks that have LocalToWorld, and then for each chunk, based on which other components it has, we select the logic we want to run for this chunk.

    What we really need is a much more wrist-friendly way of writing chunk based code, as right now it requires a lot more boilerplate than entities.foreach.
     
  9. Gen_Scorpius

    Gen_Scorpius

    Joined:
    Nov 2, 2016
    Posts:
    65
    What I found interesting that the character controller code from the unity.physics sample uses chunk api while the quite similar dots sample controller uses foreach which makes me wonder if it just boils down to preference in many cases instead of performance considerations.

    I haven't gotten that far yet where I need a complex system like unity.transform. I focus for now on the study of the physics character controller which seems to be geared for serial work units and only the last one writes to the physics velocity component. I worry about npc movement which may or may not be suitable to be covered by the same system later (probably depending on the output of the to developed decision making and pathfinding systems).
     
  10. frimarichard

    frimarichard

    Joined:
    Jul 24, 2017
    Posts:
    31
    Is this kind of granularity on the roadmap?
     
  11. Lucas-Meijer

    Lucas-Meijer

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    175
    Yes and no. Not automatic, but you can achieve the same by turning it into a single ijobchunk job and selecting the code you want to run per chunk. We have plans to improve Ijobchunk api