Random Numbers inside Unity Jobs

Feb 24, 2022

Unity's job system is fast but because it's multithreaded using random numbers inside a job is tricky. Here's one way to do it.

using UnityEngine;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;


public class Obj {
    NativeArray<Unity.Mathematics.Random> randomNumberGenerators;

    void Awake() {
        randomNumberGenerators = new NativeArray<Unity.Mathematics.Random>(Unity.Jobs.LowLevel.Unsafe.JobsUtility.MaxJobThreadCount, Allocator.Persistent);

        for (int i = 0; i < randomNumberGenerators.Length; i++) {
            randomNumberGenerators[i] = new Unity.Mathematics.Random((uint)UnityEngine.Random.Range(1, int.MaxValue));
        }
    }

    public void RunJob() {
        NativeArray<float3> positions = new NativeArray<float3>(1000, Allocator.TempJob);

        ObjJob job = new ObjJob {
            randomNumberGenerators = randomNumberGenerators,
            positions = positions
        };

        job.Schedule(positions.Length, 32).Complete();

        // do something with random positions

        positions.Dispose();
    }
}


[BurstCompile]
struct ObjJob : IJobParallelFor
{
    [Unity.Collections.LowLevel.Unsafe.NativeDisableContainerSafetyRestriction] public NativeArray<Unity.Mathematics.Random> randomNumberGenerators;
	[Unity.Collections.LowLevel.Unsafe.NativeSetThreadIndex] int threadId;
    [WriteOnly] public NativeArray<float3> positions;

    public void Execute(int i) {
        Unity.Mathematics.Random random = randomNumberGenerators[threadId];

        positions[i] = new float3(random.NextFloat(), random.NextFloat(), random.NextFloat());

        randomNumberGenerators[threadId] = random;
    }
}