IJobParallelForTransform
интерфейс в UnityEngine.Jobs
Описание
Интерфейс, позволяющий выполнять одну и ту же независимую операцию для позиции, поворота и масштаба каждой трансформации, переданной в задание.
Этот тип задания концептуально похож на IJobFor, но вместо того, чтобы итерировать по диапазону произвольных данных, он итерирует по массиву данных преобразования. Поскольку UnityEngine.Transform является управляемым типом и не может быть безопасно изменен кодом задания, этот тип задания предлагает обход этого ограничения.
Transform данные предоставляются заданию через UnityEngine.Jobs.TransformAccessArray, который обворачивает массив экземпляров UnityEngine.Transform в неуправляемый тип UnityEngine.TransformAccess и позволяет безопасно обрабатывать базовые данные параллельно рабочими потоками.
Этот тип задания имеет следующие параметры для планирования работы:
- IJobParallelForTransformExtensions.RunReadOnlyByRef запускает задание на главном потоке и немедленно завершает его, с доступом только для чтения к преобразованным данным.
- IJobParallelForTransformExtensions.ScheduleReadOnlyByRef планирует задание на асинхронный запуск, распределяя работу между несколькими рабочими потоками. Этот вариант планирования может дать наилучшую производительность, но условия гонки могут возникнуть, если задание записывает в общие или глобальные данные без надлежащей синхронизации.
- IJobForExtensions.ScheduleByRef то же самое, что выше, но задание имеет доступ чтения/записи к преобразованным данным.
Execute(int index, TransformAccess transform) выполняется один раз для каждого индекса от 0 до указанной длины, с соответствующими данными преобразования доступными через указанный параметр.RunReadOnlyByRef гарантирует, что работа Execute(int index, TransformAccess transform) метод вызывается последовательно. ScheduleReadOnlyByRef и ScheduleByRef не призывайте работу Execute метод последовательно, потому что он вызывается из нескольких рабочих потоков параллельно друг другу.
Каждая итерация должна быть независимой от других итераций, и система безопасности обеспечивает соблюдение этого правила. Индексы не имеют гарантированного порядка и выполняются на нескольких ядрах параллельно.
Для заданий, требующих доступа для чтения/записи для преобразования данных, Unity автоматически разделяет и сортирует предоставленные данные преобразования на куски, которые могут быть безопасно обработаны параллельно. Все преобразования из одной и той же иерархии преобразований будут обрабатываться одним рабочим потоком, чтобы обеспечить, что запись данных преобразования мирового пространства не вызывает условия гонки. Однако порядок, в котором преобразования в иерархии обрабатываются, не гарантируется.
Вы можете воспользоваться возвращенным JobHandle чтобы проверить, что задание завершено, или передать его другим заданиям в качестве зависимости. Когда вы передаете задание, JobHandle как зависимость, она обеспечивает выполнение заданий одно за другим на рабочих потоках.
Дополнительные ресурсы: UnityEngine.Jobs.IJobParallelForTransformExtensions.
public struct ApplyVelocityJobParallelForTransform : IJobParallelForTransform { // Jobs declare all data that will be accessed in the job // By declaring it as read only, multiple jobs are allowed to access the data in parallel [ReadOnly] public NativeArray<Vector3> velocity; // Delta time must be copied to the job since jobs generally don't have a concept of a frame. // The main thread waits for the job same frame or next frame, but the job should do work deterministically // independent on when the job happens to run on the worker threads. public float deltaTime; // The code actually running on the job public void Execute(int index, TransformAccess transform) { // Move the transforms based on delta time and velocity var pos = transform.position; pos += velocity[index] * deltaTime; transform.position = pos; } } public void ApplyVelocity_ParallelForTransform() { // Create some objects whose transforms will be processed var gameObjects = new GameObject[500]; var transforms = new Transform[500]; for (int i = 0; i < transforms.Length; ++i) { gameObjects[i] = new GameObject($"Test Object {i}"); transforms[i] = gameObjects[i].transform; } var transformAccessArray = new TransformAccessArray(transforms); var velocity = new NativeArray<Vector3>(transforms.Length, Allocator.Persistent); for (var i = 0; i < velocity.Length; ++i) velocity[i] = new Vector3(0f, 10f, 0f); // Initialize the job data var job = new ApplyVelocityJobParallelForTransform() { deltaTime = Time.deltaTime, velocity = velocity }; // If this job required a previous job to complete before it could safely begin execution, // we'd use its handle here. For this simple case, there are no job dependencies, // so a default JobHandle is sufficient. JobHandle dependencyJobHandle = default; // Schedule a parallel-for-transform job. // The method takes a TransformAccessArray which contains the Transforms that will be acted on in the job. JobHandle jobHandle = job.ScheduleByRef(transformAccessArray, dependencyJobHandle); // Ensure the job has completed. // It is not recommended to Complete a job immediately, // since that reduces the chance of having other jobs run in parallel with this one. // You optimally want to schedule a job early in a frame and then wait for it later in the frame. // Ideally this job's JobHandle would be passed as a dependency to another job that consumes the // output of this one. If the output of this job must be read from the main thread, you should call // Complete() on this job handle just before reading it. jobHandle.Complete(); // Once the job is complete, the expected processing should have occurred. // Note that accessing the value of a Transform component on the main thread automatically // completes any IJobParallelForTransform which is currently writing to that Transform. for (var i = 0; i < velocity.Length; i++) Assert.AreEqual(Time.deltaTime * velocity[i].y, transforms[i].position.y); // Native containers must be disposed manually. velocity.Dispose(); transformAccessArray.Dispose(); }
Открытые методы
| Метод | Описание |
|---|---|
| Execute | Выполняет работу по определенному индексу итерации и преобразованию. |