Search Unity

[0.0.8] Can not access ComponentArray<Class> members from job

Discussion in 'Entity Component System' started by Tudor_n, Jul 3, 2018.

  1. Tudor_n

    Tudor_n

    Joined:
    Dec 10, 2009
    Posts:
    359
    Is this intended ?


    Code (CSharp):
    1. class Data: MonoBehaviour
    2. {
    3.     NativeArray<float> SomeData;
    4. }
    5.  
    6. // In a component system somewhere
    7. [BurstCompile]
    8. struct SomeJob: IJob
    9. {
    10.     ComponentArray<Data> stuff:
    11.     public void Execute()
    12.     {
    13.         Data d = stuff[0];
    14.     }
    15. }
    16.  
    17.  
    18. //! in the component system update
    19.  
    20. new SomeJob(){
    21.     stuff = stuffGroup.GetComponentArray<Data>()
    22. }
    Produces:

    ComponentArray.cs(45,13): error: Unable to get field because it is a class type

    Compiler exception: System.InvalidOperationException: Unable to get field because it is a class type
    at Burst.Compiler.IL.ILVisitor.Ldfld (Burst.Compiler.IL.Syntax.ILInstruction inst) [0x0001b] in <19eeae212983462598cc0ee7b1756077>:0
    at Burst.Compiler.IL.ILVisitor.CompileInternal (Burst.Compiler.IL.Syntax.ILInstruction inst) [0x0043a] in <19eeae212983462598cc0ee7b1756077>:0
    at Burst.Compiler.IL.ILVerifier.CompileInternal (Burst.Compiler.IL.Syntax.ILInstruction inst) [0x00000] in <19eeae212983462598cc0ee7b1756077>:0

    And a bunch of other subsequent burst error messages.

    This, thankfully, works:

    Code (CSharp):
    1. class Data: MonoBehaviour
    2. {
    3.     NativeArray<float> SomeData;
    4. }
    5.  
    6. // In a component system somewhere
    7.  
    8. [BurstCompile]
    9. struct SomeJob: IJob
    10. {
    11.     NativeArray<float> stuff:
    12.     public void Execute()
    13.     {
    14.         stuff[0] = 1.0f;
    15.     }
    16. }
    17.  
    18.  
    19. //! in the component system update
    20.  
    21. new SomeJob(){
    22.     stuff = stuffGroup.GetComponentArray<Data>()[0].stuff
    23. }
     
  2. dartriminis

    dartriminis

    Joined:
    Feb 3, 2017
    Posts:
    157
    That is intended, you can only access value types in jobs. It's recommended that you use ComponentDataArray with IComponentData in place of ComponentArray and MonoBehaviours for jobs.
     
  3. Tudor_n

    Tudor_n

    Joined:
    Dec 10, 2009
    Posts:
    359
    Interesting. The error did not exist prior to 0.0.8. Could also see this pattern being fairly common in Hybrid approaches. I would expect that's the whole reason for ComponentArray's existence, in fact.

    As for my case, you can not have any real data storage outside of mono land. Having data in MBs is, in fact, the currently recommended way of doing this ( I'd say the only sane way for hybrid ). Doing this while having the nice auto-dependency layer tied to ComponentArray was nice, while it lasted.

    Your answer did make me curios as to why I can't access a pointer ( NativeArray memory ) through a pointer ( a class ). I guess performance reasons ( as it's hard to predict my access pattern in that component array, or its content's memory locations ). If so, a warning would of been just as good ?
     
    Last edited: Jul 3, 2018
  4. dartriminis

    dartriminis

    Joined:
    Feb 3, 2017
    Posts:
    157
    With Ecs, the recommended data storage is now IComponentData and ComponentDataArrays (Data Oriented Design approach) . If your going the hybrid approach, you can use ComponentDataWrapper to attach an IComponentData to a GameObject just as you would a MonoBehaviour. Bear in mind this is still very much preview software :)
     
  5. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    Works fine on 0.0.8.
    Code (CSharp):
    1. [Serializable]
    2. public struct CitizenData : IComponentData
    3. {
    4.     public int citizenId;
    5. }
    6.  
    7. public class Citizen : MonoBehaviour
    8. {
    9.     public CitizenData data;
    10. }
    Code (CSharp):
    1. public class CitizensManager : ComponentSystem
    2. {
    3.     //Some stuff ...
    4.     public struct SpawnCitizenData
    5.     {
    6.         public int parentBuildingIndex;
    7.         public int citizensCount;
    8.     }
    9.  
    10.     public struct AllCitizensGroup
    11.     {
    12.         public ComponentArray<Citizen>             Citizen;
    13.         public EntityArray                         Entity;
    14.         public readonly int Length;
    15.     }
    16.  
    17.     [Inject] public  AllCitizensGroup                  m_AllCitizens;
    18.  
    19.     //Some stuff ...
    20.  
    21.     struct CalcSpawnCitizensParallelJob : IJobParallelFor
    22.     {
    23.         [ReadOnly] public ComponentArray<Citizen>                  citizens;
    24.         //Some stuff ...
    25.  
    26.         public void Execute(int index)
    27.         {
    28.          
    29.             if (citizens[i].data.citizenId == 1)
    30.             {
    31.                 //Some stuff ...
    32.             }
    33.             //Some stuff ...
    34.         }
    35.     }
    36.  
    37.     protected override void OnUpdate()
    38.     {
    39.             //Some stuff ...
    40.             var calcCitizensParallelJob = new CalcSpawnCitizensParallelJob
    41.             {
    42.                 citizens  = m_AllCitizens.Citizen
    43.             };
    44.             var calcCitizensParallelHandle =
    45.                 calcCitizensParallelJob.Schedule(m_Buildings.Length, Mathf.CeilToInt(m_Buildings.Length / 8));
    46.             calcCitizensParallelHandle.Complete();
    47.             //Some stuff ...
    48.             spawnData.Dispose();
    49.             //Some stuff ...
    50.         }
    51.     }
    52. }
     
  6. Tudor_n

    Tudor_n

    Joined:
    Dec 10, 2009
    Posts:
    359
    Hmm, the only difference seems to be that you are injecting your group as opposed to using GetComponentGroup in my case. Will check this out when I get to my workstation.

    If true, it looks like a bug. To be fair, it looked like a bug anyway.