I starting work with jobs system and I want to create job which needs array of struct with simple types inside (float3 quaternion etc.)
I want to use own struct to avoid using 12 different arrays just for separated float3s and quaternions etc.
When I do something like this
NativeList<MyJob.Container> container = new NativeList<MyJob.Container>(Allocator.TempJob);
MyJob.Container cnt1 = new MyJob.Container();
cnt1.helpPos = new float3(0, 0, 0);
cnt1.helpRot = new quaternion(0, 0, 0, 1);
// ... etc.
container.Add(cnt1);
MyJob jjob = new MyJob();
JobHandle hhandle = jjob.Schedule(container.Length, 100);
hhandle.Complete();
Debug.Log(jjob.data[0].helpPos);
container.Dispose();
I getting error like:
InvalidOperationException: MyJob.data is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.
When I add [ReadOnly] there are no errors but after doing job I can’t get access to the parameters from list.
(all have default values like float3(0,0,0) )
How can I use list of struct containing allowed types inside job?
You need to show more code and specifics. It looks like it is printing out what you are writing to the list before the job based on what you have shown, which is what I would expect if you marked the list as [ReadOnly].
Alright, I prepared ready example.
Some of variables are not used but are added just to show I will need more variables in actual code, this is very simplified version:
using System.Collections.Generic;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
public class JobsTest : MonoBehaviour
{
public Transform[] toMove;
private List<MyHelperClass> helperInstances;
void Start()
{
helperInstances = new List<MyHelperClass>();
for (int i = 0; i < toMove.Length; i++)
{
MyHelperClass h = new MyHelperClass();
h.startPos = toMove[i].position; // will not be used in this example, just to show I would need more variables in real code
h.prePos = toMove[i].position; // will not be used in this example
h.startRot = toMove[i].rotation; // will not be used in this example
h.preRot = toMove[i].rotation; // will not be used in this example
h.distance = Vector3.Distance(toMove[i].position, toMove[i + (i == toMove.Length - 1 ? -1 : 1)].position);
helperInstances.Add(h);
}
}
void Update()
{
NativeList<MyJob.Container> containers = new NativeList<MyJob.Container>(Allocator.TempJob);
for (int i = 0; i < toMove.Length; i++)
{
MyJob.Container c = new MyJob.Container();
c.pos = toMove[i].position;
c.rot = toMove[i].rotation;
c.startDist = helperInstances[i].distance;
containers.Add(c);
}
MyJob job = new MyJob
{
delta = Time.deltaTime,
data = containers
};
JobHandle handle = job.Schedule(containers.Length, 100);
handle.Complete();
for (int i = 0; i < toMove.Length; i++)
{
toMove[i].position = containers[i].pos;
toMove[i].rotation = containers[i].rot;
helperInstances[i].prePos = containers[i].pos;
helperInstances[i].preRot = containers[i].rot;
}
containers.Dispose();
}
public struct MyJob : IJobParallelFor
{
public NativeList<Container> data;
public float delta;
public void Execute(int index)
{
if (index == 0) return;
Container current = data[index];
Container pre = data[index-1];
current.rot = quaternion.LookRotation(pre.pos - current.pos, new float3(0,1,0) );
float3 target = pre.pos + math.mul(current.rot, new float3(0, 0, current.startDist));
current.pos = math.lerp(current.pos, target, delta * 10f);
data[index] = current;
}
public struct Container
{
public float3 pos;
public quaternion rot;
// I would need much more floats and quaternions variables in my real code
public float startDist;
}
}
public class MyHelperClass
{
public Vector3 prePos;
public Vector3 startPos;
public Quaternion preRot;
public Quaternion startRot;
public float distance;
}
}
And I know there are transform access lists, but I will sometimes need thing like here anyway.
I include .cs file as attachment too.