Threading
The four threading rules — capture on the main thread, everything after it off-thread, autosave never touching a Unity object, and callbacks that never block.
The four rules#
- Capture on the main thread. Reading live Unity objects from a worker thread is a data race. The projector takes the framework's dispatcher and refuses on any other thread, naming the reason.
- Everything after capture is off-thread. The document is an independent snapshot, so serialization, compression, encryption, integrity and the write are pure work over bytes.
- Autosave never touches a Unity object. It asks the dispatcher for a capture on the main thread, then saves the snapshot on a worker.
- Unity callbacks never block.
OnDisable,OnApplicationPauseand scene changes capture synchronously and save asynchronously, because those callbacks cannot await and the object may not exist a frame later.
Where the work actually runs#
main thread capture (projection) ----+
|
worker serialize -> compress -> encrypt -> integrity -> write -> verify -> promoteStorage.OffloadWritesToThreadPool moves the second row off your thread. It is off by default because existing code that mutates its model immediately after calling save keeps working. A test asserts all three facts: the default stays on the caller's thread, the option leaves it, and the model is still read on the caller's thread either way.
Getting back to the main thread#
dispatcher.Post(() => transform.position = restored);
await dispatcher.RunAsync(() => Task.CompletedTask);IMainThreadDispatcher is a seam: UnityMainThreadDispatcher drives work from a player-loop system in a build and from EditorApplication.update in the Editor, with no GameObject, scene object or coroutine required. InlineMainThreadDispatcher exists for tests and headless hosts.
Restoring is also main-thread only#
UnityObjectApplier.TryRestore refuses off-thread for the same reason capture does: it writes to live objects.
Next#
- Performance — the numbers, and why the offload is measured in behaviour rather than time.
- Large saves — what to do when the snapshot itself is big.
- Limitations — the constraints stated as constraints.
Something wrong on this page? Every page here describes behaviour that is checked in the repository. If a page and the package disagree, the package wins.
Report a documentation problem · Frequently asked questions · Troubleshooting