Scheduling background jobs with Job.WithCode
The Job.WithCode
construction in the SystemBase
class runs a method as a single background job. You can also run Job.WithCode
on the main thread and take advantage of Burst compilation to speed up execution.
Using Job.WithCode
The following example uses one Job.WithCode
lambda expression to fill a native array with random numbers, and another job to add those numbers together:
public partial class RandomSumJob : SystemBase
{
private uint seed = 1;
protected override void OnUpdate()
{
Random randomGen = new Random(seed++);
NativeArray<float> randomNumbers
= new NativeArray<float>(500, Allocator.TempJob);
Job.WithCode(() =>
{
for (int i = 0; i < randomNumbers.Length; i++)
{
randomNumbers[i] = randomGen.NextFloat();
}
}).Schedule();
// To get data out of a job, you must use a NativeArray
// even if there is only one value
NativeArray<float> result
= new NativeArray<float>(1, Allocator.TempJob);
Job.WithCode(() =>
{
for (int i = 0; i < randomNumbers.Length; i++)
{
result[0] += randomNumbers[i];
}
}).Schedule();
// This completes the scheduled jobs to get the result immediately, but for
// better efficiency you should schedule jobs early in the frame with one
// system and get the results late in the frame with a different system.
this.CompleteDependency();
UnityEngine.Debug.Log("The sum of "
+ randomNumbers.Length + " numbers is " + result[0]);
randomNumbers.Dispose();
result.Dispose();
}
}
To run a parallel job, implement IJobFor
. You can use using ScheduleParallel()
to schedule the parallel job in the system's OnUpdate()
function.
Capture variables
You can't pass parameters to the Job.WithCode
lambda expression or return a value. Instead, you must capture local variables in a system's OnUpdate()
function.
If you use Schedule()
to schedule your job to run in Unity's job system, there are additional restrictions:
- You must declare captured variables as a
NativeArray
, a native container, or a blittable type. - To return data, you must write the return value to a captured
Native Array
, even if the data is a single value. However, if you useRun()
to execute the job, you can write to any captured variable.
Job.WithCode
has a set of methods that apply read-only and safety attributes to a captured native container's variables. For example, you can use WithReadOnly
to restrict access to the variable as read-only. You can also use WithDisposeOnCompletion
to automatically dispose of a container after the job finishes. For more information, see the Capturing variables section of the Job.WithCode
documentation.
Execute the Job.WithCode lambda expression
To execute the Job.WithCode
lambda expression you can use the following:
Schedule()
: Executes the method as a single, non-parallel job. Scheduling a job runs the code on a background thread and takes better advantage of all available CPU resources. You can either explicitly pass aJobHandle
toSchedule()
or, if you don't pass any dependency, the system assumes that the current system'sDependency
property represents the job's dependencies. Alternatively, you can pass in a newJobHandle
if the job has no dependencies.Run()
: Executes the method on the main thread. You can Burst compileJob.WithCode
, so if you useRun()
to execute the code, this can be faster even though it runs on the main thread. When you callRun()
, Unity automatically completes all the dependencies of theJob.WithCode
construction.
Dependencies
By default, a system uses its Dependency
property to manage its dependencies. The system adds each Entities.ForEach
and Job.WithCode
job you create to the Dependency
job handle in the order that they appear in the OnUpdate()
method.
To manage job dependencies manually, pass a JobHandle
to the Schedule
methods, which then return the resulting dependency. For more information, see the Dependency
API documentation.
For general information about job dependencies, see the documentation on Job dependencies.