Hi all,
I’m trying to write Terrain generator which uses new IJob system but I’m getting stuck at this error:
IndexOutOfRangeException: Index 369 is out of restricted IJobParallelFor range [128...191] in ReadWriteBuffer.
I assume this issue is caused when Unity is trying to write on the same variable on multiple threads. Or it is caused by something else?
Is there save way to pass ~60k size array to IJob system?
example code:
struct GenereteJob : IJobParallelFor
{
[WriteOnly] public NativeArray<float> jNoiseMap;
[ReadOnly] public NativeArray<Vector2> jOctaveOffstes;
public int jWidth;
public int jHeight;
public float jScale;
public int jOctaves;
public float jPersistence;
public float jLacunarity;
public float jMaxNoiseHeight;
public float jMinNoiseHeight;
public float jHalfWidth;
public float jHalfHeight;
public int jY;
public void Execute(int i)
{
float amplitude = 1;
float frequence = 1;
float noiseHeight = 0;
for (int ii = 0; ii < jOctaves; ii++)
{
float sampleX = (i - jHalfWidth) / jScale * frequence + jOctaveOffstes[ii].x;
float sampleY = (jY - jHalfHeight) / jScale * frequence + jOctaveOffstes[ii].y;
float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;
noiseHeight += perlinValue * amplitude;
amplitude *= jPersistence;
frequence *= jLacunarity;
}
if (noiseHeight > jMaxNoiseHeight)
{
jMaxNoiseHeight = noiseHeight;
}
else if (noiseHeight < jMinNoiseHeight)
{
jMinNoiseHeight = noiseHeight;
}
jNoiseMap[i+jWidth*jY] = noiseHeight;
}
}
public static float[,] GenerateNoiseMap (int width, int height, float scale, int octaves, float persistence, float lacunarity, Vector2 offset, int seed, bool bJob = false)
{
System.Random rnd = new System.Random(seed);
Vector2[] octaveOffstes = new Vector2[octaves];
for(int i=0; i<octaves; i++)
{
float offsetX = rnd.Next(-1000, 1000) + offset.x;
float offsetY = rnd.Next(-1000, 1000) + offset.y;
octaveOffstes[i] = new Vector2(offsetX, offsetY);
}
float[,] noiseMap = new float[width, height];
float maxNoiseHeight = float.MinValue;
float minNoiseHeight = float.MaxValue;
float halfWidth = width / 2f;
float halfHeight = height / 2f;
if (bJob)
{
float[] tempNoiseMap = new float[noiseMap.Length];
var JobNoiseMap = new NativeArray<float>(noiseMap.Length, Allocator.Persistent);
var JobOctaveOffstes = new NativeArray<Vector2>(octaveOffstes.Length, Allocator.Persistent);
var jobHandle = new List<JobHandle>();
for (int i = 0; i < octaveOffstes.Length; i++)
{
JobOctaveOffstes[i] = octaveOffstes[i];
}
for (int y = 0; y < height; y++)
{
var job = new GenereteJob()
{
jNoiseMap = JobNoiseMap,
jOctaveOffstes = JobOctaveOffstes,
jWidth = width,
jHeight = height,
jScale = scale,
jOctaves = octaves,
jPersistence = persistence,
jLacunarity = lacunarity,
jMaxNoiseHeight = maxNoiseHeight,
jMinNoiseHeight = minNoiseHeight,
jHalfWidth = halfWidth,
jHalfHeight = halfHeight,
jY = y
};
if (y == 0)
{
jobHandle.Add(job.Schedule(width, 64));
}
else
{
jobHandle.Add(job.Schedule(width, 64, jobHandle[y - 1]));
}
}
jobHandle.Last().Complete();
JobNoiseMap.CopyTo(tempNoiseMap);
JobNoiseMap.Dispose();
JobOctaveOffstes.Dispose();
for(int i=0; i<width; i++)
{
for (int j = 0; j < height; j++)
{
noiseMap[i, j] = tempNoiseMap[i + width * j];
}
}
}
else
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
float amplitude = 1;
float frequence = 1;
float noiseHeight = 0;
for (int i = 0; i < octaves; i++)
{
float sampleX = (x - halfWidth) / scale * frequence + octaveOffstes[i].x;
float sampleY = (y - halfHeight) / scale * frequence + octaveOffstes[i].y;
float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;
noiseHeight += perlinValue * amplitude;
amplitude *= persistence;
frequence *= lacunarity;
}
if (noiseHeight > maxNoiseHeight)
{
maxNoiseHeight = noiseHeight;
}
else if (noiseHeight < minNoiseHeight)
{
minNoiseHeight = noiseHeight;
}
noiseMap[x, y] = noiseHeight;
}
}
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
noiseMap[x, y] = Mathf.InverseLerp(minNoiseHeight, maxNoiseHeight, noiseMap[x, y]);
}
}
return noiseMap;
}