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 Are there any substantial reasons to use the IJobChunk workflow over the Entities.ForEach workflow?

Discussion in 'Entity Component System' started by aaarrrlll, Dec 29, 2020.

  1. aaarrrlll

    aaarrrlll

    Joined:
    Dec 29, 2020
    Posts:
    8
    Apologies if this question is very basic.

    I cannot figure out when i should use the IJobChunk workflow or the Entities.ForEach workflow when iterating over entities in a system. The reason that this concerns me, is that i see many examples employing both. I tried finding an answer in the ECS manual but all i found is this, which is quite vague. The one clear point it makes is that optional components can be processed with the IJobChunk workflow. This is not something i have seen used though.

    So the question is; when should i use which?
     
    lclemens likes this.
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,984
    aaarrrlll likes this.
  3. Timboc

    Timboc

    Joined:
    Jun 22, 2015
    Posts:
    234
    Just wanted to add a personal opinion that I think IJobChunk are great when learning - Entities.ForEach feels a lot less magical after getting comfortable with them. In particular things like how you pass a CDFE to a static method and how it relates to GetComponent<> in SystemBase. Also, like DreamingImLatios hinted at - optional components - when you want to branch logic on e.g. the presence of a Tag and are in the hot path and don't want to duplicate code to solve it. As IJobChunk iterates the chunks (rather than entities) you can branch or early out on the chunk level.
     
    aaarrrlll likes this.
  4. aaarrrlll

    aaarrrlll

    Joined:
    Dec 29, 2020
    Posts:
    8
    Thanks a lot for the fast answers. If it's the case that IJobChunk are great when learning, i will use them.
     
    charleshendry and Timboc like this.
  5. Timboc

    Timboc

    Joined:
    Jun 22, 2015
    Posts:
    234
    They are a lot more verbose so I wouldn't recommend you write *a lot* of them but I think they are a good fundamental part of Unity's ECS to understand - it's what the Entities.ForEach compiles to. Good luck :)
     
    aaarrrlll likes this.
  6. PublicEnumE

    PublicEnumE

    Joined:
    Feb 3, 2019
    Posts:
    729
    I can chime in to say that we use IJobChunk for most of our jobs. Here are the main reasons:

    1. You can schedule more than one IJobChunk per system update. That’s not supported (or at least didn’t used to be supported) for Entities.ForEach.

    2. we make good use of generic jobs in our code. They live in a shared namespace, and explicit instances of them are scheduled by multiple systems. That’s not possible with Entities.ForEach.

    3. IJobChunk gives you lower level control over how a job functions. Unity does a good job of translating Entities.ForEach jobs into high performance jobs for you. But working directly at the IJobChunk level can give you more awareness and peace of mind. Personal preference, this one. :)

    4. I believe there may still be some equivalent things you can’t do in Entities.ForEach, like decorating job variables with edge-case attributes. But time has passed since I ran into that, so maybe that part has changed.

    it’s funny that people have described them as a learning tool to use at the beginning. Because I’ve seen them as the opposite - Entities.ForEach is the one to use early on, since it does a lot of things magically. It tries to be more convenient, but sacrifices some control, visibility, and features to get there.

    Then when you want to do something ForEach doesn’t support, you drop down to a lower level and start writing more IJobChunks, since they give you more visibility and control.

    In my opinion, the lambda part of ForEach was a good idea for a way to make writing jobs more convenient. But in order for ForEach jobs to capture variables, you end up needing to write unintuitive code, like define them above the ForEach declaration without actually doing anything with them until later. I don’t think it’s a convention you would design into your code for any other reason, other than to make the capturing work.

    And personally, I think that variables defined in an IJob or IJobChunk struct are much more readable than stacking a dozen “.With()” functions as part of the ForEach syntax. Personal opinion there.
     
    Last edited: Dec 29, 2020
    aaarrrlll, Enzi, davenirline and 2 others like this.
  7. nyanpath

    nyanpath

    Joined:
    Feb 9, 2018
    Posts:
    77
    Sometimes I wonder how much time you have... I wish I had the time to do things like these as well. I've been spending a year on a mesh builder that if given a full-time treatment would have been finished already. However, I have a 9-5 that takes up more than enough of my time.
     
    aaarrrlll likes this.
  8. RecursiveEclipse

    RecursiveEclipse

    Joined:
    Sep 6, 2018
    Posts:
    298
    You also can't currently get chunk component data in a ForEach, if you're even aware that's a thing, most people aren't.
     
    Last edited: Dec 30, 2020
    aaarrrlll likes this.
  9. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,984
    Not enough, but somehow more than you despite also having a day job?
     
    aaarrrlll likes this.
  10. nyanpath

    nyanpath

    Joined:
    Feb 9, 2018
    Posts:
    77
    How long did it take you and what are you using it for?
     
    aaarrrlll likes this.
  11. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,984
    The particular job? This is like the third or fourth iteration, each of which I did in a few hours on one of my weekends. This provides more insight into what it is used for: https://github.com/Dreaming381/Lati...dventures/Part 2 - Build Collision Layer 1.md

    Unless you are referring to the framework as a whole? In that case, link to the forum thread is in my signature.

    Also, I did a dig through my public repos and this is actually my only usage of IJobChunk currently in those. I have one case where I use IJobFor on a NativeArray<ArchetypeChunk> using DynamicComponentTypeHandles, but otherwise I use Entities.ForEach way more often.
     
    charleshendry, aaarrrlll and nyanpath like this.
  12. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    909
    Can you or someone else eleborate on this? I have a bunch of Entities.ForEach in SystemBases. What is their behavior then?
     
  13. PublicEnumE

    PublicEnumE

    Joined:
    Feb 3, 2019
    Posts:
    729
    You may want to verify (or hopefully someone else where can verify) that my claim is even true anymore.

    but when Entities.ForEach was first introduced, I believe you could only schedule one of them in a system’s update function. At the time, if you needed to schedule several, sequential jobs from a single system, Unity was advising people to use IJobChunk and other explicit job structs.

    If you’re able to use multiple, sequential Entities.ForEach calls from a single system Update function, then maybe this limitation has been removed. My apologies - I can’t test this at the moment or I’d verify it as well.
     
    aaarrrlll likes this.
  14. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    You can use multiple .ForEach in a single OnUpdate now. You just need to be careful about dependencies between the jobs.

    you might need to call JobHandle.Complete() or JobHandle.CombineDependencies().
     
    aaarrrlll likes this.
  15. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    I don't ever remember any requirement of a single ForEach, could be wrong. Either way, no there is no limitation on how many ForEachs. AFAIK ForEach gets converted into an IJobChunk during codegen.

    If anything Entities.ForEach lets you ignore job handles most of the time. I suggest you read up on it.
     
    aaarrrlll likes this.
  16. adammpolak

    adammpolak

    Joined:
    Sep 9, 2018
    Posts:
    450
    Thank you @Sarkahn ! I was referencing needing to pass data in and out of these .ForEach()'s (like this) where you need to be mindful of when jobs are completed and what data you reference.
     
    aaarrrlll and PublicEnumE like this.
  17. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,653
    It never was like this :) From the ForEach beginning, you can use many of them in one OnUpdate.
     
    PublicEnumE likes this.
  18. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,994
    CDFE? what's that
     
  19. Timboc

    Timboc

    Joined:
    Jun 22, 2015
    Posts:
    234
    (Get)ComponentDataFromEntity - what backs the Has/Get/SetComponent calls inside a SystemBase - sometimes useful for example to capture and pass to a static method within the lambda when working with Entities.ForEach
     
  20. Fribur

    Fribur

    Joined:
    Jan 5, 2019
    Posts:
    127