I am working on a video game in Unity and at some point I'm facing a tough problem to solve:
The game freezes while loading level data.
Let me lay down what's happening in that process that takes a few seconds:
- load track mesh data consisting of sections, faces, vertices
- load track textures, build an atlas out of them for the mesh
- build track mesh using aforementioned data
This loading process takes a few seconds and I expect it to be even longer since I will have to load scenery which is bigger by a magnitude (not yet done).
Some of the steps in this loading process cannot be run in a background thread as they instantiate objects from Unity, which can only be done from its main thread, e.g. create a texture, mesh etc.
Attempts and ideas at solving the problem:
start a coroutine, this simply doesn't work since they are expected to run within a single frame, the loading process take hundreds of frames, a frame being 1/60th of a second
split the loading into chunks, process each at every frame, likely to be the solution but tricky
- when required, generate engine objects using a dispatcher, i.e. an async call executing in the appropriate thread, e.g. create the final texture out of raw pixels
I will focus on the second approach as it seems the right one but I am open for another approach.
What approach or pattern I could use to split a long running operation into smaller ones?
(Hope that's clear enough to you, let me know otherwise.)
Edit: Clarifications after the comments:
Basically my problem is simple but difficult to fix, simple as UI freezes because a task running in it since it requires access to it takes longer than usual; complex as on how to refactor this without rewriting the whole thing. I believe there is a simpler and equally effective approach to tackle this.
Two other ideas emerge from this:
Dispatcherapproach, I'd run the whole thing in a background thread, wrapping engine calls as needed, the UI would only freeze a bit; this is fine as it happens even on AAA games
a static loading screen, perceptually hides the problem but doesn't solve it at all