Where state belongs: Entity, Resource or Autoload
Choose data lifetime and mutation ownership; a shared session need not own the whole project.
Start with lifetime
| Data/behavior | Suitable location |
|---|---|
| One enemy health or local animation | An Entity/component inside its prefab |
| Mission objectives or current-level enemy lists | A level controller |
| Run score crossing level boundaries | An explicit session service outside the replaced root, such as Autoload |
| A configurable weapon/material description | A Resource with clear sharing policy |
| Data surviving process exit | A serialized schema in user:// |
Autoload creates an object at startup that survives CurrentScene replacement; it is not a mandatory home for every manager. A persistent application root can also organize long-lived objects. Make the intended lifetime explicit.
Control mutation
SessionState offers AddCoins/ResetRun and reports CoinsChanged. The HUD displays state and disconnects on exit. The service knows no UI path; levels should not rewrite arbitrary service internals.
For local behavior, GroupTarget2D works without GetParent or a global service: an external controller supplies ApplyDamage. The fixture creates a receiver without a parent. The group remains a dynamic set rather than a type-safe interface.
What a container choice does not solve
A Resource can be shared between instances. Do not store per-enemy mutable health in one shared configuration resource unless shared results are intentional. See Resources for loading and copying.
Autoload does not persist data to disk, make access thread-safe or prevent a second class instance. Disabling _Process does not block its methods. Application logic also defines network authority and command validation.
Verify the boundary
- Instantiate a component outside its large level: it works or explicitly reports a required dependency.
- Delete and recreate a level: local data resets, while session data survives only as intended.
- Detach and reattach the HUD: updates arrive once and the initial value is reread.
- Start a new run: an explicit command resets shared state rather than an accidental level reload.
These cases run with SessionState/SessionHud and GroupTarget2D. They establish those components boundaries rather than universal superiority of one architecture pattern.