I agree with Nikita's observation about thread safety. It might be instructive to see how to do this with
Interlocked, although I'm not convinced that it's necessarily a better solution than
WaitHandle. It's certainly fragile - I had to correct some mistakes in my first version of this answer.
The potential threading problems are:
-- read, alter a register, and write, allowing another thread to change the value in between the read and write. This is directly solved with
- If the callback is interleaved with the
Start method you could get a situation where the callback count is decremented to zero even though there are still initialisation tasks to perform, causing
LoadScene to be called early. This is solved by making
Start itself an initialisation task.
- The increment must be done before registering the callback, lest the callback decrement before
Start has done the increment.
Note that I prefer to use
try/finally with manual synchronisation, although there's certainly an argument that if the body of
Start throws an exception then we don't mind never loading the scene.
Callback private because it should never be called except as a callback, and
Start has access to it even as a private method.
I'm also tempted to make
Callback abort with a fatal error if the number of incomplete actions is less than 0, because that indicates a major logic error which you want to catch before taking the project into production.
private int incompleteActions = 0;
private void Callback()
if (Interlocked.Decrement(ref incompleteActions) <= 0)