Building Simple Audio Visualization with Unity ECS Part II — Job System
This is the second part of our journey to learn ECS on unity. If you haven’t read the previous post I recommend you to take a while to read that in order to know how the audio visualizer work with the old MonoBehavior way.
Today we’re going to take what’s written on the first part and change it into a Jobified Unity Job System.
The Job System, as explained on the Unity pages, take advantages of multiple cores that our machine have. They also guarantee some protection of multi-threading race conditions pitfalls. To make the audio visualizer Jobified, I took inspiration from here . That links have some great examples on how to structure your data, schedule your jobs, and use the results.
What the job system do is breaking your big “process” into a smaller “Jobs”, doing specific task that could be run parallelly. Job receive parameters and operates on data similar to how a method behave. Each job is self contained but it could have a dependency between each other, making other job only launch after a specific job finishes.
Unity Job System code usually have this form
1. Create Job, populate the job with data
2. Schedule the Job, you would get a JobHandle that could be used as a dependency for other jobs
3. Finish the Job by calling the Complete on the JobHandle
First, we will move the act of processing the audio visualizer data into job
As you can see all the work of scaling the cube and offseting it’s position now moved into the
SpectrumJob. There are new
NativeArray data that is declared inside the Job, those are Unity
NativeContainers that is introduced in the new job system. The general purpose of those containers is to give added safety system so you’ll get error if two scheduled jobs writing into the same
NativeContainers. The Job System also prevent accessing data from the main thread, each code executed inside the
Execute() is considered working in a separated thread from the main thread.
There’s also other rule that needs to be respected when working with the
NativeContainers with Unity Job Sytem, you could read them here.
We still need old MonoBehavior to create, schedule and complete the
SpectrumJob, as displayed here.
Update(), we create the
SpectrumJob, fill all the data needed for the Job to perform, then schedule it. The new
TransformAccessArray on the
Start() method is needed for the
SpectrumJob to work. Since previously when we create the cube, it’s transform is not laid out linearly on the memory, we need to create a new
TransformAccess data with the array of transforms for the
SpectrumJob so it could be worked on. On
LateUpdate, we ask the
jobHandle to Complete the job, then we copy the data from
SpectrumJob into our
prevSpectrums buffers, this buffer will be feeded into the Job again in the next update.
In this video you could see the results with two audio channels, left and right, I omitted the necessary code above for the two channels, but it is basically the same idea but you need to get the spectrum data from the left (0) and the right (1) channel.
Previously on the old MonoBehavior workflow we cannot have this many cube to be displayed smoothly, but changing our code to work with the new JobSystem, our Audio Visualizer now could handle two channels simultaneously!.
With this the job system is done, we’ll move on the next part, we’ll talk about how to move this into our end goal Unity ECS form.
Until next time!