# Async Code
Unity 6's **`Awaitable`** is the first-party way to write `async` / `await` in gameplay code without paying the cost of a .NET `Task` on every wait. This series compares `Awaitable` to **iterator coroutines** and to `Task`, covers the built-in wait helpers and thread switches, and treats **cancellation** as a required part of the API — especially `destroyCancellationToken` and `Application.exitCancellationToken`.
**Target:** Unity **6000.5+**. The same `Awaitable` surface is in Unity 6 generally, including **Unity 6.3 LTS (6000.3.27f2+)** for VR work in this vault ([[0.Choosing a Unity Version]]). Confirm any edge-case behaviour (for example, how a given package's handle converts to an awaitable) against the Editor you are on.
> [!warning] Code not compiled
> Scripts were checked against the Unity 6000.5 `Awaitable` Scripting API and the "Asynchronous programming with the Awaitable class" manual on 2026-11-10. **They have not been compiled or run in Unity.**
> [!note] Verification status
> **Verified APIs:** `Awaitable` as an async return type; `IsCompleted`, `Cancel`, `LogExceptionsAndForget`; static `NextFrameAsync`, `EndOfFrameAsync`, `FixedUpdateAsync`, `WaitForSecondsAsync`, `FromAsyncOperation`, `MainThreadAsync`, `BackgroundThreadAsync`; continuation rule (resume on main if called from main, otherwise thread pool, except the two thread-switch helpers); `WaitForSecondsAsync` is main-thread only and completes on the main thread; pooled instances **must not be awaited twice**; `destroyCancellationToken`; `Application.exitCancellationToken`; cancellation throws `OperationCanceledException`.
> **Not verified:** a first-party `Awaitable` extension on Addressables 2.9 handles (use `handle.Task`, a coroutine, or Addressables 4.x `ToAwaitable()` — [[3. Loading Instantiating and Releasing]]); exact interaction of `LogExceptionsAndForget` with custom log handlers.
## Parts
| # | Note | Covers |
|---|---|---|
| 1 | [[1. Awaitable versus Coroutines and Task]] | When to use each model, pooling, SynchronizationContext |
| 2 | [[2. Awaitable Waits and Thread Switches]] | The built-in wait helpers, `FromAsyncOperation`, background work |
| 3 | [[3. Cancellation Tokens]] | `destroyCancellationToken`, `exitCancellationToken`, linked tokens |
| 4 | [[4. Worked Examples - Scenes Delays and Loads]] | Scene load, a hit-react delay, wrapping an Addressables handle |
| 5 | [[5. Async Pitfalls]] | Double-await, fire-and-forget, dead objects, Play Mode exit |
## Design lens (Level Up!)
Timing *is* feel: hit-stop, door telegraphs, camera blends, and onboarding prompts (Levels 9-12 in [[Level Up! (Review)]]) are all "wait, then do the next thing" problems. Coroutines have done this in Unity for years. `Awaitable` gives you the same non-blocking waits with clearer errors and cancellation, so a destroyed enemy does not keep running a coroutine you forgot to stop.
## Patterns used (Game Programming Patterns)
- **Command / Subclass Sandbox** - an async method is a sequence of actions; keep it readable, cancel the whole sequence.
- **Object Pool** - `Awaitable` instances themselves are pooled (official warning: do not await one instance twice).
- **Observer** - cancellation tokens are the cooperative "please stop" signal, not a callback soup.
See [[Game Programming Patterns (Review)]].
## Related (existing)
- [[SceneManagement in Unity 6]] / [[Level Manager]]
- [[Addressables]] and [[3. Loading Instantiating and Releasing]]
- [[Unity Test Framework]] — async `Task` tests are supported; do not return `Awaitable` from a test method ([[3. UnityTest Async Tests and Domain Reloads]])
- [[2. CPU Allocations and Incremental GC]] — `Task` has more allocation and scheduling cost than `Awaitable`
- [[Localization]] — `GetLocalizedStringAsync` and initialization operations
- [[Input System]] — do not "await a button" if a proper action callback already exists
- [[Cinemachine 3]] — blends are usually time-driven by the camera brain; you await *your* beat, not the brain's internals, unless you have a documented hook
## Sources
- Asynchronous programming with the Awaitable class (6000.5): https://docs.unity.com/en-us/engine/6000.5/manual/scripting/optimization/async-await-support
- Awaitable completion and continuation (6000.5): https://docs.unity.com/en-us/engine/6000.5/manual/scripting/optimization/async-await-support/async-awaitable-continuations
- `Awaitable` Scripting API: https://docs.unity3d.com/6000.5/Documentation/ScriptReference/Awaitable.html
- `Awaitable.WaitForSecondsAsync`: https://docs.unity3d.com/6000.5/Documentation/ScriptReference/Awaitable.WaitForSecondsAsync.html
- `Awaitable.Cancel`: https://docs.unity3d.com/6000.5/Documentation/ScriptReference/Awaitable.Cancel.html
- `MonoBehaviour.destroyCancellationToken`: https://docs.unity3d.com/6000.5/Documentation/ScriptReference/MonoBehaviour-destroyCancellationToken.html
- `Application.exitCancellationToken`: https://docs.unity3d.com/ScriptReference/Application-exitCancellationToken.html