Search Unity

Bug TransformAspect not working ComponentLookup<Translation> in IJobEntity

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

  1. instriker_911

    instriker_911

    Joined:
    Mar 31, 2022
    Posts:
    27
    Versions
    Unity 2022.2.0b10.git.2306062
    "com.unity.entities": "1.0.0-exp.8"

    Goal
    Use the new TransformAspect.LookAt to look at an other entity Position using a ComponentLookup<Translation> in a IJobEntity, eg.:

    Code (CSharp):
    1.  
    2. public struct HunterBehavior : IComponentData
    3. {
    4.     public Entity TargetEntity;
    5. }
    6. public partial struct DemoJob : IJobEntity
    7. {
    8.     [ReadOnly] public ComponentLookup<Translation> getTranslation;
    9.     public void Execute(ref TransformAspect transformAspect, ref HunterBehavior hunter)
    10.     {
    11.         var targetPosition = getTranslation[hunter.TargetEntity];
    12.         transformAspect.LookAt(targetPosition.Value);
    13.     }
    14. }
    15. public partial class DemoSystem : SystemBase
    16. {
    17.     protected override void OnUpdate()
    18.     {
    19.         var getTranslation = this.GetComponentLookup<Translation>(isReadOnly: true);
    20.         this.Dependency = new DemoJob { getTranslation = getTranslation }.Schedule(this.Dependency);
    21.     }
    22. }
    23.  

    Issue

    The IJobEntity autogenerated code above generate the following error when trying to use a ComponentLookup<T> that use of of the component included by the aspect:

     
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Problem here is that you're accessing same data while reading & writing via lookup (Translation).
    This was not supported prior either.

    Try storing target position in a separate job, and writing Translation afterwards in a different one.
     
    instriker_911 likes this.
  3. instriker_911

    instriker_911

    Joined:
    Mar 31, 2022
    Posts:
    27
    Before converting to the aspect I could. The reason is that I could have a read-only translation and a writable rotation.

    In the case of using a look at, I want to update the rotation only while seeking translation of other entities.

    The workaround is acceptable in my case, so maybe it's not a bug, but then a feature request. The aspect is nice, but it's an all or nothing on the read / writes. It would be nice to be able to disable safety checks (like for the native containers) if we want to use the aspect while the safety checks at compile time think it's unsafe.
     
  4. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    992
    Solution using the TransformAspect.Lookup :

    Code (CSharp):
    1. [BurstCompile]
    2. public partial struct MoveIstsyem : ISystem
    3. {
    4.     private TransformAspect.Lookup _transformLookup;
    5.  
    6.     public void OnCreate(ref SystemState state)
    7.     {
    8.         _transformLookup = new TransformAspect.Lookup(ref state, true);
    9.     }
    10.  
    11.     public void OnDestroy(ref SystemState state)
    12.     {
    13.     }
    14.  
    15.     [BurstCompile]
    16.     public void OnUpdate(ref SystemState state)
    17.     {
    18.         _transformLookup.Update(ref state);
    19.         foreach (var(transform, otherEntity,entity) in SystemAPI.Query<TransformAspect, RefRO<FollowEntity>>().WithEntityAccess())
    20.         {
    21.  
    22.             float3 direction = _transformLookup[otherEntity.Value].Position - transform.Position;            
    23.             transform.Position += math.normalize(direction) * SystemAPI.Time.DeltaTime;
    24.         }
    25.     }
    26. }
     
    Last edited: Oct 16, 2022
    vanyfilatov and instriker_911 like this.
  5. instriker_911

    instriker_911

    Joined:
    Mar 31, 2022
    Posts:
    27

    Thank you for the info, I missed the part where the lookup on aspect where on a different model (TransformAspect.Lookup VS state.GetComponentLookup / state.GetBufferLookup). It may come an handy in the future for that part. Still think it would be nice to have the same API for discoverability (eg.: state.GetAspectLookup)

    As for the example, that's nice to be able to use the lookup directly inside an ISystem, but it still fail with the same erreur when trying to use in an IJobEntity, eg.:

    Code (CSharp):
    1.  
    2.     public struct HunterBehavior : IComponentData
    3.     {
    4.         public Entity TargetEntity;
    5.     }
    6.  
    7.     public partial struct DemoJob : IJobEntity
    8.     {
    9.         [ReadOnly] public TransformAspect.Lookup _transformLookup;
    10.         public void Execute(ref TransformAspect transform, ref HunterBehavior hunter)
    11.         {
    12.             var targetPosition = _transformLookup[hunter.TargetEntity];
    13.             transform.LookAt(targetPosition.Position);
    14.         }
    15.     }
    16.     public partial struct DemoSystem : ISystem
    17.     {
    18.         private TransformAspect.Lookup _transformLookup;
    19.  
    20.         public void OnCreate(ref SystemState state)
    21.         {
    22.            
    23.             _transformLookup = new TransformAspect.Lookup(ref state, isReadOnly: true);
    24.         }
    25.  
    26.         public void OnDestroy(ref SystemState state)
    27.         {
    28.         }
    29.  
    30.         public void OnUpdate(ref SystemState state)
    31.         {
    32.             _transformLookup.Update(ref state);
    33.             state.Dependency = new DemoJob { _transformLookup = _transformLookup }.Schedule(state.Dependency);
    34.         }
    35.     }
    36.  
    foreach in ISystem have many limitations at the moment, mainly the one where it can only run on the main thread. In my real scenarios, I have different jobs. Which would mean I would had to either all the other jobs to be inside the system.

    At least, I have decent workarounds in different scenarios, but it would be nice to be able to have something that work more straightforward with IJobEntity.
     
  6. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    992
    Can't you use the lookup as not read only ( second parameter false) ?
     
  7. instriker_911

    instriker_911

    Joined:
    Mar 31, 2022
    Posts:
    27
    I tried it (while also removing the [ReadOnly] attribute) but without success. Still getting the error:

     
  8. instriker_911

    instriker_911

    Joined:
    Mar 31, 2022
    Posts:
    27
    Update:

    The TransformAspect.Lookup was a good track to follow. Adding the the [NativeDisableContainerSafetyRestriction] on the TransformAspect.Lookup of the IJobEntity works. So as long as you know that it can't have side effects in your situation, this should be good.

    Code (CSharp):
    1. public partial struct DemoJob : IJobEntity
    2. {
    3.     [NativeDisableContainerSafetyRestriction]
    4.     [ReadOnly] public TransformAspect.Lookup _transformLookup;
    5.     public void Execute(ref TransformAspect transform, ref HunterBehavior hunter)
    6.     {
    7.         var targetPosition = _transformLookup[hunter.TargetEntity];
    8.         transform.LookAt(targetPosition.Position);
    9.     }
    10. }
    So this allow to use the TransformAspect as the lookup when updating it in a IJobEntity.Execute ref parameter with the less compromises.
     
    WAYNGames likes this.
  9. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    992
    Does that work ?

    Code (CSharp):
    1. public partial struct DemoJob : IJobEntity
    2. {
    3.    
    4.     public TransformAspect.Lookup _transformLookup;
    5.     public void Execute(Entity entity, ref HunterBehavior hunter)
    6.     {
    7.        _transformLookup[entity].LookAt(targetPosition.Position);
    8.     }
    9. }
    With

    Code (CSharp):
    1. _transformLookup = new TransformAspect.Lookup(ref state, false);
    2.  
     
    instriker_911 likes this.
  10. instriker_911

    instriker_911

    Joined:
    Mar 31, 2022
    Posts:
    27
    Yes it works and I do not need the [NativeDisableContainerSafetyRestriction], so I think it's the best solution at the moment. It would be nice to be able to pass a ReadOnly container variant, but at least with this solution I have the advantages of being able to keep the same architecture with almost no code changes.

    Thank you!
     
    WAYNGames likes this.