Loading a lot of Objects or executing a lot of tasks as fast as possible in conjunction with keeping your app responsive – has always been a challenge when you only have a Single Thread at your disposal, as you have to manage timing for suspensions and switching between tasks.
Most modern apps don’t have this problem, as they run in Multiple Threads which are seemingly communicating with each other.
In many cases the User Interface (UI) is drawn in Main thread and tasks are executed in parallel background threads, making UI rendering independent of background tasks. Meaning that, if background task hangs, UI will still keep running i.e. stay responsive and capable of informing the user of what’s going on.
Unfortunately Unity is not thread safe(as of Aug, 2018) – all calls to Unity API should be done only from Main Thread , otherwise you’ll probably get an Exception. (Yes I’m aware of the Jobs system and it’s awesome, but not quite there yet)
There is also one more thing to note: in Unity order of execution of certain functions really matters sometimes and we can’t run them in parallel.
We had an issue with generating a lot of mesh files and textures from our custom serialized format (files were loaded in parallel, but generation of unity objects was serial). If we generated them all at once without waiting for UI redraw – Progress Bar would freeze until very end of the operation, which kinda killed the sole purpose of having a progress indicator.
Image: Progress bar freezes until the very end (10x fast forward)
That could be fixed by waiting for the end of the frame for each file. Though we will waste a lot of precious time for no reason.
Image: Waiting for the end of the frame for each file
The goal was to generate as much objects per frame as possible. Also to give UI some time to redraw, before continuing with object generation.
To do this I created a “Loop Slicer”, which slices loops into chunks. Each chunk has around 16ms (Less than 1 Frame time on 60FPS, I will experiment with this later) to execute. UI callbacks are executed between each chunk.
Implementation is very simple; Loop checks the timer before going to next index and will be paused if 16ms limit was exceeded. It will continue After executing callback and waiting for passed waiter.
Image: Loop Slicer Chunks
I short Loop slicer’s main purpose is to split a bunch of little tasks between frames in the most efficient way possible(at least for me lol).
And that’s about it for today guys.
Oh and just in case you find this useful here’s the download link:
Feel free to leave a comment down bellow if you have any questions, issues or just found a bug haha.