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 Correct way to get Aspects in an IJobChunk?

Discussion in 'Entity Component System' started by PublicEnumE, Nov 1, 2022.

  1. PublicEnumE

    PublicEnumE

    Joined:
    Feb 3, 2019
    Posts:
    729
    I can't find an example of how to properly use Aspects in an IJobChunk. Is the feature supported in IJobChunk?

    The closest thing I've found is
    SystemAPI.GetAspectRW<T>(Entity entity)
    . Is that the intended way for an aspect to be acquired in an IJobChunk?

    It just seems wrong - it seems like there should be a direct method to get an aspect from the chunk, similar to ArchetypeChunk.GetNativeArray<T>(). But If I understand correctly, called to SystemAPI methods triggers codegen, so...maybe it's still efficient in the end?

    Some guidance about getting Aspects from inside of an IJobChunk would be much appreciated, if anyone knows better than I do.
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,653
    No. Aspects is a codegen, IJobChunk is not a codegen processed job type.
     
  3. PublicEnumE

    PublicEnumE

    Joined:
    Feb 3, 2019
    Posts:
    729
    That is a bummer, to say the least. :(

    It doesn’t seem like it should be necessary to code-Gen the job to support Aspects in IJobChunk.

    For example, this could compile fine, and code-gen that runs for the Aspect type could do the work to make sure this chunk method returns the right NativeArray of Aspects:

    Code (CSharp):
    1. public struct MyJob : IJobChunk
    2. {
    3.     AspectTypeHandle<TransformAspect> transformAspectTypeHandle;
    4.  
    5.     public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    6.     {
    7.         NativeArray<TransformAspect> transformAspects = chunk.GetNativeArray(transformAspectTypeHandle);
    8.     }
    9. }
    Or, if there's concern about creating and populating all those Aspects for the array, this API could be designed to build an populate a single Aspect on demand, for a specific entity:

    Code (CSharp):
    1. public struct MyJob : IJobChunk
    2. {
    3.     AspectTypeHandle<TransformAspect> transformAspectTypeHandle;
    4.  
    5.     public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    6.     {
    7.         TransformAspect transformAspect = chunk.GetAspectForEntity(transformAspectTypeHandle, 0);
    8.     }
    9. }
    This is what I was kind of expecting. Such a useful new tool not being supported in the most versatile job type is concerning. I'm worried that someone on the dev team might think this wouldn't have value.
     
    Last edited: Nov 1, 2022
  4. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    908
    Code (CSharp):
    1. var job2 = new Job()
    2. {                
    3.     TransformAspect_WriteHandle = new TransformAspect.TypeHandle(ref state, false)
    4. };
    in job:
    Code (CSharp):
    1. public TransformAspect.TypeHandle TransformAspect_WriteHandle;
    in execute:
    Code (CSharp):
    1. var ltws = TransformAspect_WriteHandle.Resolve(chunk);
    The only thing I don't know is how to write back. IJE passes a ref to the Execute method but refs not working with Resolve.
     
  5. PublicEnumE

    PublicEnumE

    Joined:
    Feb 3, 2019
    Posts:
    729
    Unfortunately this only works after codegen runs. TransformAspect is the built-in exception. If you try this with a custom Aspect type, it won't work.
    MyAspect.TypeHandle
    won't exist.
     
  6. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    908
    Well, yeah. Aspects are a codegen feature. What's the problem with letting it run?
    Custom IAspects TypeHandles are codegen'd just fine for me.
     
  7. scottjdaley

    scottjdaley

    Joined:
    Aug 1, 2013
    Posts:
    152
    I just tried converting one of my IJobEntity based systems that uses a custom IAspect to an IJobChunk. Seems to find the TypeHandle just fine. However, you do have to let unity compile and codegen the aspect first so the workflow isn't great.

    Here is the IJobEntity version:

    Code (CSharp):
    1. [BurstCompile]
    2. public partial struct TransformSpringSystem : ISystem
    3. {
    4.     public void OnCreate(ref SystemState state) { }
    5.  
    6.     public void OnDestroy(ref SystemState state) { }
    7.  
    8.     [BurstCompile]
    9.     public void OnUpdate(ref SystemState state)
    10.     {
    11.         new Job { DeltaTime = state.WorldUnmanaged.Time.DeltaTime }.ScheduleParallel();
    12.     }
    13.  
    14.     [BurstCompile]
    15.     private partial struct Job : IJobEntity
    16.     {
    17.         public float DeltaTime;
    18.  
    19.         private void Execute(TransformSpringAspect spring)
    20.         {
    21.             spring.Update(DeltaTime);
    22.         }
    23.     }
    24. }
    And here is the IJobChunk version:

    Code (CSharp):
    1. [BurstCompile]
    2. public partial struct TransformSpringTestSystem : ISystem
    3. {
    4.     private TransformSpringAspect.TypeHandle _aspectTypeHandle;
    5.  
    6.     private EntityQuery _query;
    7.  
    8.     public void OnCreate(ref SystemState state)
    9.     {
    10.         _aspectTypeHandle = new TransformSpringAspect.TypeHandle(ref state, false);
    11.  
    12.         _query = state.GetEntityQuery(new EntityQueryDesc { All = TransformSpringAspect.RequiredComponents });
    13.     }
    14.  
    15.     public void OnDestroy(ref SystemState state) { }
    16.  
    17.     [BurstCompile]
    18.     public void OnUpdate(ref SystemState state)
    19.     {
    20.         _aspectTypeHandle.Update(ref state);
    21.  
    22.         state.Dependency = new Job
    23.         {
    24.             AspectTypeHandle = _aspectTypeHandle, DeltaTime = state.WorldUnmanaged.Time.DeltaTime,
    25.         }.ScheduleParallel(_query, state.Dependency);
    26.     }
    27.  
    28.     [BurstCompile]
    29.     private struct Job : IJobChunk
    30.     {
    31.         public TransformSpringAspect.TypeHandle AspectTypeHandle;
    32.  
    33.         public float DeltaTime;
    34.  
    35.         public void Execute(
    36.             in ArchetypeChunk chunk,
    37.             int unfilteredChunkIndex,
    38.             bool useEnabledMask,
    39.             in v128 chunkEnabledMask)
    40.         {
    41.             TransformSpringAspect.ResolvedChunk aspects = AspectTypeHandle.Resolve(chunk);
    42.  
    43.             for (int entityIndex = 0; entityIndex < chunk.Count; entityIndex++)
    44.             {
    45.                 TransformSpringAspect aspect = aspects[entityIndex];
    46.                 aspect.Update(DeltaTime);
    47.             }
    48.         }
    49.     }
    50. }
    In my opinion, there should be generic AspectTypeHandle<> and an AspectLookup<> types that are the aspect analogs of ComponentTypeHandle<> and ComponentLookup<>. Perhaps there is a technical reason why this isn't possible, but I think it would make it much easier to use aspects in jobs.
     
  8. AbrakaDabraSutra

    AbrakaDabraSutra

    Joined:
    Sep 3, 2021
    Posts:
    6
    How did you create the RequiredComponents field? Or was it already available? Cannot find it in the selection.

    Using ECS 1.0.0-pre.44 Unity Version 2022.2.12f1.
     
  9. scottjdaley

    scottjdaley

    Joined:
    Aug 1, 2013
    Posts:
    152
    Yeah, this was one of the fields that is generated by the aspect codegen. But it looks like it was removed in one of the later releases. Support for aspects has been greatly improved in the latest version of ECS. We can now add aspects directly to an EntityQuery with
    WithAspect()
    .

    I haven't tried using an aspect in an IJobChunk in this release, but I think everything else besides constructing the query should look about the same.

    Btw, If you ever want to know how to make things work in IJobChunk, a simple way is to write a system using IJobEntity and an Aspect and then inspect the codegen'd IJobChunk.
     
  10. AbrakaDabraSutra

    AbrakaDabraSutra

    Joined:
    Sep 3, 2021
    Posts:
    6
    Being able to call WithAspect() solved my issue. Thank you all for your answers :)