多くの場合、あるジョブは別のジョブの結果に依存します。例えば、ジョブ A はNativeArray
に書き込みを行い、それをジョブ B が入力として使用します。依存するジョブをスケジュールするときに、ジョブシステムにそのような依存関係を伝える必要があります。依存するジョブが終了するまで、ジョブシステムは依存するジョブを実行しません。1 つのジョブが複数のジョブに依存する場合があります。
各ジョブが前のジョブに依存するようなジョブのチェーンを作ることもできます。しかし、ジョブを実行する前に依存関係が完了するのを待たなければならないため、依存関係はジョブの実行を遅らせます。依存するジョブを完了させるには、まずそのジョブが依存しているジョブと、それらのジョブが依存しているジョブを完了させなければなりません。
ジョブの Schedule
メソッドを呼び出すと、JobHandle
を返します。コード内で JobHandle
を他のジョブの依存関係として使用することができます。ジョブが別のジョブの結果に依存している場合は、以下のように、最初のジョブの JobHandle
をパラメーターとして Schedule
メソッドに渡すことができます。
JobHandle firstJobHandle = firstJob.Schedule();
secondJob.Schedule(firstJobHandle);
ジョブに多くの依存関係がある場合は、JobHandle.CombineDependencies
メソッドを使用してそれらを統合できます。CombineDependencies
を使うと、依存関係を Schedule
メソッドに渡すことが可能です。
NativeArray<JobHandle> handles = new NativeArray<JobHandle>(numJobs, Allocator.TempJob);
// Populate `handles` with `JobHandles` from multiple scheduled jobs...
JobHandle jh = JobHandle.CombineDependencies(handles);
以下は複数の依存関係を持つ複数のジョブの例です。ジョブコード (MyJob
と AddOneJob
) を Update
と LateUpdate
コードとは別のファイルに置くのが効率的ですが、わかりやすくするために、この例では 1 つのファイルに置いています。
using UnityEngine;
using Unity.Collections;
using Unity.Jobs;
public class MyDependentJob : MonoBehaviour
{
// Create a native array of a single float to store the result. This example waits for the job to complete.
NativeArray<float> result;
// Create a JobHandle to access the results
JobHandle secondHandle;
// Set up the first job
public struct MyJob : IJob
{
public float a;
public float b;
public NativeArray<float> result;
public void Execute()
{
result[0] = a + b;
}
}
// Set up the second job, which adds one to a value
public struct AddOneJob : IJob
{
public NativeArray<float> result;
public void Execute()
{
result[0] = result[0] + 1;
}
}
// Update is called once per frame
void Update()
{
// Set up the job data for the first job
result = new NativeArray<float>(1, Allocator.TempJob);
MyJob jobData = new MyJob
{
a = 10,
b = 10,
result = result
};
// Schedule the first job
JobHandle firstHandle = jobData.Schedule();
// Setup the data for the second job
AddOneJob incJobData = new AddOneJob
{
result = result
};
// Schedule the second job
secondHandle = incJobData.Schedule(firstHandle);
}
private void LateUpdate()
{
// Sometime later in the frame, wait for the job to complete before accessing the results.
secondHandle.Complete();
// All copies of the NativeArray point to the same memory, you can access the result in "your" copy of the NativeArray
// float aPlusBPlusOne = result[0];
// Free the memory allocated by the result array
result.Dispose();
}
}