Skip to content

Instantly share code, notes, and snippets.

@runevision
Last active April 5, 2025 08:05
Show Gist options
  • Save runevision/e25310fbdd88a90a4a6a67fff69cb16d to your computer and use it in GitHub Desktop.
Save runevision/e25310fbdd88a90a4a6a67fff69cb16d to your computer and use it in GitHub Desktop.
Using Unity Burst directly on methods without jobs - unofficial example code
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using UnityEngine;
// This example code demonstrates using Unity Burst directly on a static method without jobs.
// Unity NativeArrays can't be used directly in Unity Burst methods (only in Burst jobs),
// so we have to pass pointers to arrays instead.
//
// This PointerArray wrapper can be created from a NativeArray via simple implicit assignment:
//
// NativeArray<float> floatNativeArray = new NativeArray<float>(1000, Allocator.Persistent);
// PointerArray<float> floatPointerArray = floatNativeArray;
//
// The PointerArray can then be used like an array itself, including getting the Length.
public unsafe struct PointerArray<T> where T : unmanaged {
public readonly T* Array;
public readonly int Length;
public T this[uint index] {
get { return Array[index]; }
set { Array[index] = value; }
}
public T this[int index] {
get { return Array[index]; }
set { Array[index] = value; }
}
public PointerArray(T* Array, int Length) {
this.Array = Array;
this.Length = Length;
}
public static implicit operator PointerArray<T>(NativeArray<T> a) {
return new PointerArray<T>((T*)a.GetUnsafePtr(), a.Length);
}
}
[BurstCompile]
public class BurstMethodTester : MonoBehaviour {
enum Mode { NonBurstMethod, NonBurstJob, BurstMethod, BurstJob }
void Start() {
Execute(Mode.NonBurstMethod);
Execute(Mode.NonBurstJob);
Execute(Mode.BurstMethod);
Execute(Mode.BurstJob);
}
void Execute(Mode mode) {
var input = new NativeArray<float>(10000000, Allocator.Persistent);
var output = new NativeArray<float>(1, Allocator.Persistent);
for (int i = 0; i < input.Length; i++)
input[i] = 1.0f * i;
var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
if (mode == Mode.NonBurstMethod) {
PointerArray<float> outputArr = output;
ExecuteNonBurstMethod(input, ref outputArr);
}
else if (mode == Mode.NonBurstJob) {
var job = new MyNonBurstStruct { Input = input, Output = output };
job.Schedule().Complete();
}
else if (mode == Mode.BurstMethod) {
PointerArray<float> outputArr = output;
ExecuteBurstMethod(input, ref outputArr);
}
else if (mode == Mode.BurstJob) {
var job = new MyBurstStruct { Input = input, Output = output };
job.Schedule().Complete();
}
stopwatch.Stop();
Debug.Log("Took " + stopwatch.ElapsedMilliseconds + "ms with mode " + mode
+ "\nThe result of the sum is: " + output[0]);
input.Dispose();
output.Dispose();
}
[BurstCompile]
public static void ExecuteBurstMethod(in PointerArray<float> Input, ref PointerArray<float> Output) {
float result = 0.0f;
for (int i = 0; i < Input.Length; i++) {
result += Input[i];
}
Output[0] = result;
}
public static void ExecuteNonBurstMethod(in PointerArray<float> Input, ref PointerArray<float> Output) {
float result = 0.0f;
for (int i = 0; i < Input.Length; i++) {
result += Input[i];
}
Output[0] = result;
}
[BurstCompile(CompileSynchronously = true)]
private struct MyBurstStruct : IJob {
[ReadOnly]
public NativeArray<float> Input;
[WriteOnly]
public NativeArray<float> Output;
public void Execute() {
float result = 0.0f;
for (int i = 0; i < Input.Length; i++) {
result += Input[i];
}
Output[0] = result;
}
}
private struct MyNonBurstStruct : IJob {
[ReadOnly]
public NativeArray<float> Input;
[WriteOnly]
public NativeArray<float> Output;
public void Execute() {
float result = 0.0f;
for (int i = 0; i < Input.Length; i++) {
result += Input[i];
}
Output[0] = result;
}
}
}
@runevision
Copy link
Author

What version of Unity did you have to use for this to work?

I was using this in Unity 2019.4 and later. I don't know in which version it started working.

@AndrzejKebab
Copy link

What version of Unity did you have to use for this to work?

Burst has always been available for static methods.

And I don't see any need for PointerArray<T> to be required for a method to use NativeArray<T> with burst.
Like I did

[BurstCompile]
private static void CompleteBurst(ref NativeArray<JobHandle> jobHandles, byte batchSize)
[BurstCompile]
private static void ScheduleBurst(ref NativeArray<JobForData<T>> jobArray, ref JobSchedulerBase baseScheduler, byte batchSize)

and it worked.
I may have misunderstood something.

@runevision
Copy link
Author

I don't see any need for PointerArray<T> to be required for a method to use NativeArray<T> with burst.

It's needed in Unity 2019.4 where it's not possible to pass NativeArrays to Burst-compiled methods. In some later version it became possible (I can't remember which version).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment