Search Unity

Bug Can't use IAspect Lookup inside an IJobEntity

Discussion in 'Entity Component System' started by instriker_911, Oct 22, 2022.

  1. instriker_911

    instriker_911

    Joined:
    Mar 31, 2022
    Posts:
    27
    Goal
    Be able to lookup other entities IAspect from inside an IJobEntity.

    Tentative

    Here is a sample of what I tried:

    Code (CSharp):
    1.  
    2. public readonly partial struct DemoAspect : IAspect
    3. {
    4.     public readonly Entity entity;
    5.     public readonly RefRO<Translation> Translation;
    6. }
    7.  
    8. public partial struct DemoSystem : ISystem
    9. {
    10.     public void OnCreate(ref SystemState state)
    11.     {
    12.     }
    13.  
    14.     public void OnDestroy(ref SystemState state)
    15.     {
    16.     }
    17.  
    18.     public void OnUpdate(ref SystemState state)
    19.     {
    20.         // OK:
    21.         var translationLookup = state.GetComponentLookup<Translation>(isReadOnly: true);
    22.         new DemoJobWithComponentLookup() { lookup = translationLookup }.Run();
    23.  
    24.         // Getting error SGJE0009: DemoSystem.DemoJobWithAspectLookup contains non-value type field lookup.
    25.         var demoAspectLookup = new DemoAspect.Lookup(ref state, isReadOnly: true);
    26.         new DemoJobWithAspectLookup() { lookup = demoAspectLookup }.Run();
    27.     }
    28.  
    29.     private partial struct DemoJobWithComponentLookup : IJobEntity
    30.     {
    31.         public ComponentLookup<Translation> lookup;
    32.  
    33.         public void Execute(Entity entity, in Parent parent)
    34.         {
    35.             var lookupedUp = lookup[parent.Value];
    36.         }
    37.     }
    38.  
    39.     private partial struct DemoJobWithAspectLookup : IJobEntity
    40.     {
    41.         public DemoAspect.Lookup lookup;
    42.  
    43.         public void Execute(Entity entity, in Parent parent)
    44.         {
    45.             var lookupedUp = lookup[parent.Value];
    46.         }
    47.     }
    48. }
    49.  
    But I failed to make it work at the moment. It get the following error:

    SGJE0009: DemoSystem.DemoJobWithAspectLookup contains non-value type field lookup

    But, the Lookup is a value-type, so it looks like a code gen bug where the autoGen Lookup for an IAspect is not detected as a value-type, as well all it's fields.

    Question

    What would be the best workaround at the moment to use the aspect lookup inside a Job?

    I tried to do create new Aspect, but the generated constructor is private (var lookup = new DemoAspect(entity, TranslationComponentLookup.GetRefRO(entity));).

    I also tried to use the CreateAspect, but this requires the SystemState (which is a ref struct), so it cannot be passed to a IJobEntity (would require ref partial struct DemoJobWithAspectLookupWorkaround : IJobEntity, but you cannot be an ref struct AND implement an interface at the same time). And we also cannot use NativeReference<SystemState>.

    The best I came out with is to add a static helper method into the IAspect and do the same thing as the IAspect.Lookup does, but it does requires me to keep all the refs to all the required Lookups (in my real secenario, I have up to 7), which is quite annoying:

    Code (CSharp):
    1.  
    2. public readonly partial struct DemoAspect : IAspect
    3. {
    4.     public readonly Entity entity;
    5.     public readonly RefRO<Translation> Translation;
    6.  
    7.     public static DemoAspect DemoAspectWokaround(Entity entity, RefRO<Translation> translation)
    8.     {
    9.         return new DemoAspect(entity, translation);
    10.     }
    11. }
    12.  
    13.     private partial struct DemoJobWithAspectLookupWorkaround : IJobEntity
    14.     {
    15.         public ComponentLookup<Translation> lookup;
    16.  
    17.         public void Execute(Entity entity, in Parent parent)
    18.         {
    19.             var lookupedUp = DemoAspect.DemoAspectWokaround(parent.Value, lookup.GetRefRO(parent.Value));
    20.         }
    21.     }
    22.  
    So, better ideas?
     
  2. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    It's weird that
    TransformAspect.Lookup
    doesn't generate the SGJE0009 error, but custom Aspects do.

    Because it most certainly is a bug, my temporary workaround is just to copy the codegen'ed Lookup implementation into my own IAspect struct, and rename "Lookup" into something else. Seems to work well for me so far. Just need to remember to re-copy whenever the code changes.
     
    Last edited: Oct 23, 2022
    instriker_911 likes this.
  3. scottjdaley

    scottjdaley

    Joined:
    Aug 1, 2013
    Posts:
    163
    Yeah I think this is a bug. Especially since TransformAspect.Lookup appears to work like @Singtaa mentioned. The DemoAspect.Lookup type is a value type, so I think codegen is just tripping up on this for some reason.
     
    NoPants_ and Occuros like this.
  4. instriker_911

    instriker_911

    Joined:
    Mar 31, 2022
    Posts:
    27
    I confirm that if I copy/paste the Lookup auto-gen code in my own class that I don't have the issue. It will be a OK workaround for now as I won't have to change the architecture of the project.
     
  5. Occuros

    Occuros

    Joined:
    Sep 4, 2018
    Posts:
    300
    It seems to still be the case in 1.0.0-pre.15
     
    instriker_911 likes this.
  6. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,235
    While not ideal, this worked for me, thanks.
     
  7. instriker_911

    instriker_911

    Joined:
    Mar 31, 2022
    Posts:
    27
    FYI, after updating to EditorVersion: 2022.2.8f1 with "com.unity.entities": "1.0.0-pre.44" the original issues is now fixed! (and note that the above workaround no longer works)