public struct MoveExistingVegetation : IJobForEach<Tree>
{
public NativeArray<float3> NewTreePositions;
public float2 NewMiddlePoint;
public int Counter;
public void Execute(ref Tree tree)
{
if (!Utils.IsPositionInsideCurrentMiddlePoint(tree.position, NewMiddlePoint))
{
if (Counter < NewTreePositions.Length)
{
tree.position = NewTreePositions[Counter];
//BREAKPOINT
Counter++;
}
}
}
}
And this is the code which is trying to extract the data:
//BREAKPOINT
var job = new MoveExistingVegetation()
{
NewMiddlePoint = newId,
NewTreePositions = blablabla
};
var handle = job.Schedule(this);
handle.Complete();
//BREAKPOINT
PrefabManager.Log("We moved Trees: " + job.Counter);
What i want: Iterate over each Tree, sometimes do stuff, then return the count of all trees where i did something.
The Problem is that Count is ALWAYS! 0.
Even if i put breakpoints on the lines i marked with //BREAKPOINT, i see that everything is run in order (eg the job is constructed, then inside we count up 2 times, then i get outside the job, but here the values are lost.
Job is a struct and struct is passed by value.
You should use NativeArray<int> Counter instead of the int, with length equal to cores count and with job thread index or run in the single thread.
public struct MoveExistingVegetation : IJobForEach<Tree>
{
public NativeArray<float3> NewTreePositions;
public float2 NewMiddlePoint;
public NativeArray<int> Counter;
public void Execute(ref Tree tree)
{
if (!Utils.IsPositionInsideCurrentMiddlePoint(tree.position, NewMiddlePoint))
{
if (Counter[0] < NewTreePositions.Length)
{
tree.position = NewTreePositions[Counter[0]];
//BREAKPOINT
Counter[0] = Counter[0] + 1;
}
}
}
}
var counter = new NativeArray<int>(1, Allocator.TempJob);
var job = new MoveExistingVegetation()
{
NewMiddlePoint = newId,
NewTreePositions = blablabla,
Counter = counter,
};
var handle = job.ScheduleSingle(this);
handle.Complete();
//BREAKPOINT
PrefabManager.Log("We moved Trees: " + counter[0]);
counter.Dispose();
There is a racecondition happening: I have 750 Objects, but when iterating over each one, i count most of the times only 740/744.
Is there a way to force the job on only a single thread or is there a different way to do this @ilih Maybe ForEachWithEntitie? What is the index used for?
This way you safely write to counter and then get counter sum.
But I don’t have advice on how to do multithread read from NewTreePositions without getting same value.
var counter = new NativeArray<int>(JobsUtility.MaxJobThreadCount, Allocator.TempJob);
var job = new MoveExistingVegetation()
{
NewMiddlePoint = newId,
NewTreePositions = blablabla,
Counter = counter,
};
var handle = job.Schedule(this);
handle.Complete();
//BREAKPOINT
PrefabManager.Log("We moved Trees: " + sum(counter));
counter.Dispose();
struct MoveExistingVegetation : IJobForEachWithEntity<Tree>
{
public NativeArray<float3> NewTreePositions;
public float2 NewMiddlePoint;
[NativeDisableParallelForRestriction]
public NativeArray<Unity.Mathematics.Random> Counter;
[Unity.Collections.LowLevel.Unsafe.NativeSetThreadIndex]
int threadId;
public void Execute(ref Tree tree)
{
if (!Utils.IsPositionInsideCurrentMiddlePoint(tree.position, NewMiddlePoint))
{
if (Counter[threadId] < NewTreePositions.Length)
{
tree.position = ???;
Counter[jobIndex] = Counter[jobIndex] + 1;
}
}
}
}