Search Unity

NativeArrays inside Jobs

Discussion in 'Entity Component System' started by andreicfsteaua, Mar 19, 2020.

Thread Status:
Not open for further replies.
  1. andreicfsteaua

    andreicfsteaua

    Joined:
    Nov 18, 2019
    Posts:
    36
    Hi, i am a beginner in unity dots and in general but i am focusing on learning dots. The problem that i encountered is that i cannot create NativeArrays of any kind of allocator inside jobs.
    Code (CSharp):
    1.  
    2. Entities.WithAll<BowTag>().ForEach((Entity entity, in Translation translation, in Rotation bowRotation) =>
    3.         {
    4.             NativeArray<quaternion> rotations = new NativeArray<quaternion>(1, Allocator.Temp);
    5.             NativeArray<float3> translations = new NativeArray<float3>(1, Allocator.Temp);
    6.             NativeArray<float3> results = new NativeArray<float3>(1, Allocator.Temp);
    7.             rotations[0] = bowRotation.Value;
    8.             translations[0] = translation.Value + displacement - bowDisplacement;
    9.             CalculateQuaternionAndFloat3MultiplicationJob job = new CalculateQuaternionAndFloat3MultiplicationJob
    10.             {
    11.                 rotation = rotations,
    12.                 point = translations,
    13.                 result = results
    14.             };
    15.             JobHandle jobHandle = job.Schedule(1, 1);
    16.             jobHandle.Complete();
    17.             commandBuffer.AddComponent<MovementData>(entity, new MovementData { speed = speed, target = results[0] });
    18.             rotations.Dispose();
    19.             translations.Dispose();
    20.             results.Dispose();
    21.         }).WithoutBurst().Run();
    displacement and bowDisplacement are float3 values outside of the Entities.ForEach
    I have tried to do some workarounds but all failed. As you see I hoped non burst compiled jobs can create at least Allocator.Temp but they cannot.
    Can someone give me a way to actually to do this? (Preferably with burst compiled version) Thank you in advance.
     
  2. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
    You need to create the native arrays outside of the job and then pass them in to be used. In your case (where you call a job from within another job), you should be able to re-use them no?
     
  3. andreicfsteaua

    andreicfsteaua

    Joined:
    Nov 18, 2019
    Posts:
    36
    It does not let me, it says
    The managed class type `System.IntPtr` is not supported. Loading from a non-readonly static field `Unity.Jobs.IJobParallelForExtensions.ParallelForJobStruct`1<CalculateQuaternionAndFloat3MultiplicationJob>.jobReflectionData` is not supported
    Code (CSharp):
    1. NativeArray<quaternion> rotations = new NativeArray<quaternion>(1, Allocator.TempJob);
    2.         NativeArray<float3> translations = new NativeArray<float3>(1, Allocator.TempJob);
    3.         NativeArray<float3> results = new NativeArray<float3>(1, Allocator.TempJob);
    4.         commandBuffer.SetComponent<MovementData>(playerEntity, new MovementData { speed = speed, target = displacement });
    5.         Entities.WithAll<BowTag>().ForEach((Entity entity, in Translation translation, in Rotation bowRotation) =>
    6.         {
    7.             rotations[0] = bowRotation.Value;
    8.             translations[0] = translation.Value + displacement - bowDisplacement;
    9.             CalculateQuaternionAndFloat3MultiplicationJob job = new CalculateQuaternionAndFloat3MultiplicationJob
    10.             {
    11.                 rotation = rotations,
    12.                 point = translations,
    13.                 result = results
    14.             };
    15.             JobHandle jobHandle = job.Schedule(1, 1);
    16.             jobHandle.Complete();
    17.             commandBuffer.AddComponent<MovementData>(entity, new MovementData { speed = speed, target = results[0] });
    18.         }).Run();
    19.         rotations.Dispose();
    20.         translations.Dispose();
    21.         results.Dispose();
    Code (CSharp):
    1. public struct CalculateQuaternionAndFloat3MultiplicationJob : IJobParallelFor
    2. {
    3.     [ReadOnly] public NativeArray<quaternion> rotation;
    4.     [ReadOnly] public NativeArray<float3> point;
    5.     [WriteOnly] public NativeArray<float3> result;
    6.  
    7.     public void Execute(int index)
    8.     {
    9.         float num1 = rotation[index].value.x * 2f;
    10.         float num2 = rotation[index].value.y * 2f;
    11.         float num3 = rotation[index].value.z * 2f;
    12.         float num4 = rotation[index].value.x * num1;
    13.         float num5 = rotation[index].value.y * num2;
    14.         float num6 = rotation[index].value.z * num3;
    15.         float num7 = rotation[index].value.x * num2;
    16.         float num8 = rotation[index].value.x * num3;
    17.         float num9 = rotation[index].value.y * num3;
    18.         float num10 = rotation[index].value.w * num1;
    19.         float num11 = rotation[index].value.w * num2;
    20.         float num12 = rotation[index].value.w * num3;
    21.         float3 _result;
    22.         _result.x = (float)((1.0 - ((double)num5 + (double)num6)) * (double)point[index].x + ((double)num7 - (double)num12) * (double)point[index].y + ((double)num8 + (double)num11) * (double)point[index].z);
    23.         _result.y = (float)(((double)num7 + (double)num12) * (double)point[index].x + (1.0 - ((double)num4 + (double)num6)) * (double)point[index].y + ((double)num9 - (double)num10) * (double)point[index].z);
    24.         _result.z = (float)(((double)num8 - (double)num11) * (double)point[index].x + ((double)num9 + (double)num10) * (double)point[index].y + (1.0 - ((double)num4 + (double)num5)) * (double)point[index].z);
    25.         result[index] = _result;
    26.     }
    27. }
     
  4. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    AFAIK you can't schedule a job inside a Entities.ForEach, you will need to do an Entities.ForEach to group the data needed for the job, then schedule the job with dependency on that ForEach.
     
  5. andreicfsteaua

    andreicfsteaua

    Joined:
    Nov 18, 2019
    Posts:
    36
    Is it better to make an entityQuery, store the components in arrays and then make a separate job that will include the 1st one and run that one?
     
  6. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    That was my first thought, experiment with that then measure the performance to see if it satisfy your needs
     
  7. GXMark

    GXMark

    Joined:
    Oct 13, 2012
    Posts:
    515
    I have a problem which i hope is going to be memory efficient using a job system. Let's say i have a job which calls out to an end point remotely to get a Json string. which obviously varies in length. If i want to gain access to this Json string, do i need to allocate a native array outside of the job with a MaxSize allocation? And would i need to set the size of the JSon in another variable so i could get the String back outside of the job?

    Questions about this (assuming i'm doing this correctly)

    Would this max allocation of this native array be wasteful in terms of multiple calls to the job would require allocating this max array everytime?

    Would there be a far better approach to calling endpoints in a multi-threaded engagement that did not have these memory setup issues?
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,497
    Please don't hijack threads for your own subject. It's super easy to create your own.

    Thanks.
     
Thread Status:
Not open for further replies.