- Home /
How to manage expensive startup/initialization operations without Unity hanging?
I've seen questions similar to this, but not one that's been answered.
On startup I need to do a bunch of expensive work, which takes 2-3 seconds (read & parse XML, generate ~10k meshes etc). Unsurprisingly the UI hangs, so on a Mac you get the beachball.
I have tried using coroutines;
public class GameManager
{
private bool buildStarted = false;
void Update() {
if (Input.GetKeyDown("f") && !buildStarted) {
buildStarted = true;
StartCoroutine(doCreateWorld());
}
}
void Start (){}
IEnumerator doCreateWorld()
{
MeshManager.Init (); // cheap
yield return new WaitForFixedUpdate();
RenderManager.Init (); // expensive
yield return new WaitForFixedUpdate();
OSM.Territory.Instance.BuildTerritory (); // very expensive
yield return new WaitForFixedUpdate();
}
...and in the built-in Profiler I can see (I think!) that the work is now being split across 4 frames, which helps a bit, and does give some insight into what's going on (unlike not using coroutines..).
So, am I using co-routines correctly here? Should I split the expensive tasks into smaller, coroutined tasks? (I am already doing some multithreading in there.) The question is, how can I stop Unity hanging and remain responsive to the player?
Answer by Dave-Carlile · Feb 12, 2016 at 01:41 PM
Yes, that is a good use of Coroutines. Just keep doing what you started - amortize the cost of long operations across many frames. You can use threading too if you want, but that can add a lot more complexity to deal with synchronization, and the fact that you must call (most) Unity API functions from the main thread.
Answer by alankemp · Feb 12, 2016 at 01:45 PM
Yes, that is a good way to do this.
If you are building lots of meshes inside BuildTerritory(), make that a coroutine as well and yield every N (100 or 500 or 1000) meshes.
Also a good & correct answer thank you very much, but Accepted Dave's as it was first sorry :)
Answer by valyard · Feb 15, 2016 at 03:57 PM
You need to think about three things:
What you DO need to generate at runtime.
From what data you want to generate stuff at runtime.
How you are going to spread tasks while generating stuff over time.
The question number (3) has been pretty much answered: slice your work in tasks and do them one by one frame over frame giving control to the system frequently so your app wouldn't look totally frozen. Some progress bar would be nice too.
If you don't depend on Unity API you can as well do these tasks in a separate thread leaving main thread for something more useful.
But questions (1) and (2) are also very important. Why are you generating everything at runtime? Can you generate all this stuff at build time? Can you partially generate something at build time? I guess you answered these questions already if you are generating things at runtime, but anyway.
Question (2) is about how you store/load data from which you want to generate stuff. People usually use JSON or XML which are slow and generate a lot of garbage requiring expensive GC passes. If you want to parse dynamic JSON you'd better use built-in JSON parser in Unity 5.3. If data source is not dynamic you can pregenerate it into Unity ScriptableObject which will be loaded by internal serialization mechanism and will be much faster.
Also a good answer, and sensible questions! Except for a camera and a plane, the entire world is procedurally generated, so I need to do a lot of work at runtime. Being slow to parse is the trade-off for the strictness of X$$anonymous$$L, naturally, and I will be serialising the parsed DO$$anonymous$$ at some point in the future. I envisage the finished project containing serialised parsed files, not raw X$$anonymous$$L, and the user will select one before building the world (think of them as "level configurations").
Your answer
Follow this Question
Related Questions
A lot of time taken by AttributeHelperEngine.GetDefaultExecutionOrderFor() at Android app startup 0 Answers
Physics not initializing right away upon Play Testing in the editor 1 Answer
Does Unity support application bootstrapping? 1 Answer
Android: slow at start, then speeds up. Can the initialization be forced? 0 Answers