Tier 2 · DOTS full stack

Pitfalls: DOTS, SubScenes & Burst

Baker isolation, structural changes, Burst cache.

Baker isolation, structural changes, Burst cache.

Generalized pitfalls from shipped and active projects. Index: the pitfalls page. All entries LOCKED evidence. Status: locked (empirical, seen in shipped/active projects).

  • BAKERS-DO-NOT-SEE-THE-MAIN-SCENE — bakers cannot reliably find main-scene MonoBehaviours; they run in an isolated SubScene context. Check: bakers read only their authoring component and referenced assets. See also SUBSCENE-RUNTIME-BOUNDARY (the ecs core page). Status: locked (empirical, seen in shipped/active projects).
  • DO-NOT-NAME-A-NESTED-CLASS-BAKER — a nested class called Baker shadows Baker<T> and fails to compile (CS0308). Check: name bakers <Authoring>Baker. Status: locked (empirical, seen in shipped/active projects).
  • MONOBEHAVIOUR-FILE-NAME-MATCHES-CLASS — a MonoBehaviour/ScriptableObject whose file name differs from the class cannot be added ("needs to derive from MonoBehaviour"). Check: one Unity object type per file, file named after it. Status: locked (empirical, seen in shipped/active projects).
  • NO-STRUCTURAL-CHANGES-INSIDE-QUERY-FOREACH — calling structural EntityManager APIs inside an idiomatic SystemAPI.Query foreach throws. Check: record into an EntityCommandBuffer and play back after the loop. Status: locked (empirical, seen in shipped/active projects).
  • DESTROY-BY-QUERY-AND-LINKED-GROUPS — DestroyEntity(EntityQuery) fails when a LinkedEntityGroup points at entities outside the query. Check: destroy roots through an ECB (which follows linked groups) or include children. Status: locked (empirical, seen in shipped/active projects).
  • BAKE-PREFABS-FROM-ASSETS — a baker's GetEntity(prefab) must receive a project Prefab asset, not a scene instance. Check: authoring fields for spawnable prefabs reference assets only. Status: locked (empirical, seen in shipped/active projects).
  • SPAWNER-AUTHORING-OFF-THE-PREFAB — a baker that creates additional entities must not sit on the prefab it spawns. Check: spawners live on separate authoring objects. Status: locked (empirical, seen in shipped/active projects).
  • KEEP-SCENE-TAGS-ON-CLONES — do not strip SceneTag/SceneSection from runtime clones to "detach" them. Why: it changes archetype and breaks section unload bookkeeping. Status: locked (empirical, seen in shipped/active projects).
  • SKINNED-PREFABS-BECOME-COMPANIONS — SkinnedMeshRenderer+Animator prefabs bake as companion GameObjects unless a skinning package converts them. Check: budget companions as GameObjects; use an ECS animation solution for crowds. Status: locked (empirical, seen in shipped/active projects).
  • CROSS-BOUNDARY-REFERENCES-USE-BAKED-MARKERS — references across the main-scene/SubScene boundary break at play; query a baked marker component instead. Status: locked (empirical, seen in shipped/active projects).
  • DEFAULT-WORLD-NOT-WORLD-ZERO — MonoBehaviour-side ECS access targets World.DefaultGameObjectInjectionWorld (or the named client world), never World.All[0]. Why: with netcode, several worlds exist and order varies. Status: locked (empirical, seen in shipped/active projects).
  • INITIALIZEONLOAD-SUBSCRIPTIONS-STACK — [InitializeOnLoadMethod] runs every domain reload; subscribing to static events there without unsubscribing stacks handlers. Check: unsubscribe before subscribing. Status: locked (empirical, seen in shipped/active projects).
  • ONVALIDATE-AUTOFILL-BEFORE-GUARDS — OnValidate auto-fill must run before any debounce/early-return guard. Why: non-serialized guard flags reset unpredictably, skipping the fill. Status: locked (empirical, seen in shipped/active projects).
  • BURST-JOB-FIELD-CHANGES-CAN-NO-OP — adding a field to a Burst job struct can silently do nothing until the Burst cache is invalidated. Check: after job layout changes, force a Burst recompile and assert the new output. See also EDITOR-BURST-CAN-SKIP-A-RECOMPILE. Status: locked (empirical, seen in shipped/active projects).
  • COMPLETE-JOBS-BEFORE-OUT-OF-BAND-RENDER — code calling Camera.Render during Play must complete tracked jobs first. Status: locked (empirical, seen in shipped/active projects).
  • ENTITY-PREFABS-ONLY-BAKE-IN-SUBSCENES — a main-scene "catalog" baker is dormant. Check: catalogs of entity prefabs live in a SubScene. Status: locked (empirical, seen in shipped/active projects).
  • SUBSCENE-IMPORT-MISSES-NESTED-ASSET-EDITS — the SubScene importer does not dependency-track a material/mesh swapped inside a baked prefab, nor a referenced ScriptableObject's own fields read in Bake. Check: declare dependencies (DependsOn) for every asset whose fields a baker reads; reimport after nested edits. Status: locked (empirical, seen in shipped/active projects).
  • HOLD-NO-BUFFER-ACROSS-STRUCTURAL-CHANGE — a DynamicBuffer handle is invalidated by any later add/remove on the entity. Check: do all structural adds first, then GetBuffer and fill. Status: locked (empirical, seen in shipped/active projects).
  • NO-ENGINE-NAMESPACE-SEGMENTS — a project namespace segment named after an engine type (.Debug, .Editor) hijacks bare references. Check: avoid engine type names as namespace segments, or fully qualify (UnityEngine.Debug). Status: locked (empirical, seen in shipped/active projects).
  • DONTSAVE-OBJECTS-OUTLIVE-PLAY — runtime-created objects flagged HideFlags.DontSave are not destroyed at Play exit. Check: destroy them explicitly on exit. See also DONTSAVE-IS-INVISIBLE-TO-FINDOBJECTSBYTYPE. Status: locked (empirical, seen in shipped/active projects).