I'm trying to make a system where the player can do a RTS-like drag-to-select of tiles in a box to mark trees to be chopped or ores to be mined.
I'm testing this system on a large scale, possibly selecting 300x300 or up to 500x500 tiles per frame. For this, I thought jobs + burst would be a good idea. Every time the cursor moves, I check this if this large array of tiles is inside the bounds of the map (a 100x100 rectangle), but it's worth noting this system might be doing other checks as well.
However, using Unity's profiler (deep profile) I don't even use the returned array for anything and I'm getting pretty awful results:
It seems like the actual jobs themselves are taking up a tiny fraction of the time (tiny green columns inside the marked red area) but something else on the main thread is bottlenecking it. Here's some of the popups that occur when I click on some of the huge blue bars in the main thread:
Am I bottlenecking the main thread by initially filling out the NativeArray on the mainthread before even starting the jobs?
Here's the code for the main thread method:
private void UpdateBoxSelection()
{
Vector3Int newEndNode = Map.GridPosFromMousePos();
if (newEndNode == EndNode) { return; }
SelectedNodes.Clear();
EndNode = newEndNode;
var lowerLeftTile = new Vector3(Mathf.Min(StartNode.x, EndNode.x), Mathf.Min(StartNode.y, EndNode.y));
var upperRightTile = new Vector3(Mathf.Max(StartNode.x, EndNode.x), Mathf.Max(StartNode.y, EndNode.y));
int howManyToCheck = (Mathf.Abs(EndNode.x - StartNode.x) + 1) * (Mathf.Abs(EndNode.y - StartNode.y) + 1);
var uncheckedNodes = new NativeArray<float3>(howManyToCheck, Allocator.TempJob);
int index = 0;
for (int x = (int) lowerLeftTile.x; x <= upperRightTile.x; x++)
{
for (int y = (int) lowerLeftTile.y; y <= upperRightTile.y; y++)
{
uncheckedNodes[index] = new float3(x, y, 0);
index++;
}
}
var job = new ReallyToughParallelJob
{
UncheckedNodes = uncheckedNodes,
xMin = Map.Instance.Rect.xMin,
xMax = Map.Instance.Rect.xMax,
yMin = Map.Instance.Rect.yMin,
yMax = Map.Instance.Rect.yMax
};
JobHandle handle = job.Schedule(howManyToCheck, 1000);
handle.Complete();
uncheckedNodes.Dispose();
}
And the code for the Job:
[BurstCompile]
public struct ReallyToughParallelJob : IJobParallelFor
{
public NativeArray<float3> UncheckedNodes;
[ReadOnly] public float xMin;
[ReadOnly] public float xMax;
[ReadOnly] public float yMin;
[ReadOnly] public float yMax;
public void Execute(int index)
{
float3 newNode = UncheckedNodes[index];
if (Contains(newNode)) { UncheckedNodes[index] = newNode; }
else { UncheckedNodes[index] = float3.zero; }
}
public bool Contains(float3 point)
{
return point.x >= (double) xMin && point.x < (double) xMax && point.y >= (double) yMin && point.y < (double) yMax;
}
}