1 min read
25 Sep

После выхода Unity Jobs не сразу стало возможно создавать свои джобы, просто апи было не в публичном доступе. Сейчас же это возможно и давайте разберемся как это делать. Для начала определимся что же мы хотим сделать. Давайте возьмем самый простой вариант и напишем аналог IJob:

public struct Job : IJobSingle {
  public void Execute() {
  }
}

Т.е. мы хотим сделать стандартную однопоточную джобу (многопточные делаются не сильно дольше), что нам для этого необходимо:

1. Интерфейс и скелет

2. Инициализация джобы

3. Сама джоба

С интерфейсом все просто:

[JobProducerType(typeof(IJobSingleExtensions.JobProcess<>))]
public interface IJobSingle {
     void Execute();
}

public static unsafe class IJobSingleExtensions {
     public static JobHandle Schedule<T>(this T jobData, JobHandle inputDeps = default) where T : struct, IJobSingle {}
     internal struct JobProcess<T> where T : struct, IJobSingle {}
}

Обратите внимание, что JobProducerType говорит нам о том, что этот интерфейс не абы кто, а это интерфейс великой джобы ;)

Далее, иницилизация джобы. Мы должны вызвать сообщить шедуллеру, что в принципе у нас есть чего крутить. Для того, чтобы это заработало, нам нужно объявить инициализацию и вызвать ее в методе Schedule: 

public static unsafe class IJobSingleExtensions {
     public static JobHandle Schedule<T>(this T jobData, JobHandle inputDeps = default) where T : struct, IJobSingle {
     var parameters = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), JobProcess<T>.Initialize(), inputDeps, ScheduleMode.Single);
     return JobsUtility.Schedule(ref parameters);
}

internal struct JobProcess<T> where T : struct, IJobSingle {
     private static System.IntPtr jobReflectionData;
     public static System.IntPtr Initialize() {
          if (jobReflectionData == System.IntPtr.Zero) {
               jobReflectionData = JobsUtility.CreateJobReflectionData(typeof(T), typeof(T), (ExecuteJobFunction)Execute);
          }
          return jobReflectionData;
     }
     
     public delegate void ExecuteJobFunction(ref T jobData, System.IntPtr additionalData, System.IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex);
     public static void Execute(ref T jobData, System.IntPtr additionalData, System.IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex) {
     }
}

Ну и финально - мы добавляем в наш Execute само выполнение:

public static void Execute(ref T jobData, System.IntPtr additionalData, System.IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex) { 
     jobData.Execute();
}
Comments
* The email will not be published on the website.