Topic 5 · DOTS
Pitfalls: DOTS, SubScenes & Burst
Baker isolation, structural changes, Burst cache.
Generalized pitfalls from shipped and active projects. Record your own project's traps the same way: Keeping a project pitfall file. 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
BakershadowsBaker<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
EntityManagerAPIs inside an idiomaticSystemAPI.Queryforeach throws. Check: record into anEntityCommandBufferand play back after the loop. Status: locked (empirical, seen in shipped/active projects). - DESTROY-BY-QUERY-AND-LINKED-GROUPS —
DestroyEntity(EntityQuery)fails when aLinkedEntityGrouppoints 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).
- 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), neverWorld.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.Renderduring 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
DynamicBufferhandle is invalidated by any later add/remove on the entity. Check: do all structural adds first, thenGetBufferand 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.DontSaveare 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).