Search Unity

Post Processing HasComponent away

Discussion in 'Entity Component System' started by Lukas_Kastern, Aug 12, 2020.

  1. Lukas_Kastern

    Lukas_Kastern

    Joined:
    Aug 31, 2018
    Posts:
    97
    Currently SystemBase code like this:
    Code (CSharp):
    1. Entities.ForEach( ( Entity ent, ref MapUnitColor mapUnitColor, in ApplyColorBasedUponUsability colouring ) =>
    2. {
    3.     mapUnitColor.Value = HasComponent<IsUsable>( ent ) ? colorBasedUponUsability.UsableColor : colorBasedUponUsability.NotUsableColor;
    4. }).Run();
    Results in code like this:
    Code (CSharp):
    1. [MethodImpl(MethodImplOptions.NoInlining)]
    2. public void IterateEntities(ref ArchetypeChunk chunk, [NoAlias] ref LambdaParameterValueProviders.Runtimes runtimes)
    3. {
    4.     int count = chunk.Count;
    5.     for (int i = 0; i < count; i++)
    6.     {
    7.         OriginalLambdaBody(runtimes.runtime_ent.For(i), ref runtimes.runtime_color.For(i), in runtimes.runtime_colouring.For(i));
    8.     }
    9. }
    10.  
    11. private void OriginalLambdaBody(Entity ent, ref MapUnitColor mapUnitColor, in ApplyColorBasedUponUsability colorBasedUponUsability)
    12. {
    13.     mapUnitColor.Value = (_ComponentDataFromEntity_IsUsable_0.HasComponent(ent) ? colorBasedUponUsability.UsableColor : colorBasedUponUsability.NotUsableColor);
    14. }
    Currently everytime we call the OriginalLamdaBody we check if the entity we iterate upon has the component.
    Wouldn't it be possible to do a chunk based lookup and branch upon that inside the IterateEntities method?


    Is the performance gain we would get from that negligible?
    Or am i just missing something?
     
  2. Timboc

    Timboc

    Joined:
    Jun 22, 2015
    Posts:
    238
    You're correct. It also uses CDFE rather than chunk.exists - possibly rand access calls when they don't need to be (I'm not entirely sure). It's a cost to be aware of and imo one of the main reasons to still consider using the much more verbose IJobChunk if you have something like this is in the hot path. That said, the difference can be fairly negligible depending on number of entities, density of chunks etc. There have been mentions of a possible Chunk.ForEach API or similar to help with this (https://forum.unity.com/threads/lambdas-optional-icds.788258/#post-5259905) - but that was a long time ago so I'm not expecting anything soon.
     
    Last edited: Aug 12, 2020
    Lukas_Kastern likes this.
  3. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,269
    The other alternative is to use two ForEach loops like this:
    Code (CSharp):
    1. Entities.WithAll<IsUsable>().ForEach( ( ref MapUnitColor mapUnitColor, in ApplyColorBasedUponUsability colouring ) =>
    2. {
    3.     mapUnitColor.Value = colorBasedUponUsability.UsableColor ;
    4. }).Run();
    5.  
    6. Entities.WithNone<IsUsable>().ForEach( ( ref MapUnitColor mapUnitColor, in ApplyColorBasedUponUsability colouring ) =>
    7. {
    8.     mapUnitColor.Value = colorBasedUponUsability.NotUsableColor ;
    9. }).Run();