После выхода 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(); }