t1k:unity:dots-core:ecs
| Field | Value |
|---|---|
| Module | dots-core |
| Version | 2.3.2 |
| Effort | medium |
| Tools | — |
Keywords: archetype, auto-destroy, component, cooldown, cooldown timer, CooldownTickHelper, CooldownTimer, csv, DeadTagLifetimeSystem, despawn, DeterministicRandom, dirty, dirty flag, DirtyTag, DOTS, ECS, editor utilities, entity component system, event cleanup, EventCleanupHelper, flat index, grid math, GridMath, ICooldownState, IEnableableComponent signal, lifetime, Lifetime, LifetimeSystem, one-frame event, respawn, respawn reset, RespawnResetHelper, seed guard, SelectNearestTargetSystem, shared primitives, stat ratio, StatMath, system, target selection, TargetEntity, targeting, TargetSelection, TargetSelectionMode, TargetSelector, team, team affiliation, TeamId, timer, unit prefab, weighted sampling, WeightedSampler
How to invoke
Section titled “How to invoke”/t1k:unity:dots-core:ecsUnity DOTS ECS Core
Section titled “Unity DOTS ECS Core”Contribute back on bug-fix: when this session resolved a non-obvious DOTS gotcha (silent IJobEntity skip, query dedupe, structural-change invalidation, baking order, etc.) that future sessions would benefit from, emit a marker BEFORE your final summary so the lesson reaches the kit:
[t1k:lesson kit="theonekit-unity" skill="dots-core:ecs" fragment="references/<file>.md" reason="<one-line>"]Thelesson-collector.cjsStop hook captures it; a background/t1k:sync-backsub-agent files the PR on origin. Seerules/telemetry.mdfor the full pipeline. (Theauto-lesson-from-skill-edit.cjsPostToolUse hook intheonekit-corev1.16+ does this automatically when the same session edits a gotchas reference file — but emitting the marker yourself is still the canonical path when the fix lives in code only.)
Terminology
Section titled “Terminology”- DOTS — Data-Oriented Technology Stack
- ECS — Entity Component System
- ECB — EntityCommandBuffer
Skill Purpose
Section titled “Skill Purpose”Reference for Unity Entities 1.4.x patterns. Covers the full authoring-to-runtime pipeline: baking GameObjects into entities, defining components, writing Burst-compiled systems, querying entities, and performing structural changes safely.
IAspect is deprecated in Entities 1.4+ (will be removed in a future release) — prefer direct SystemAPI.Query usage.
Related skills:
dots-jobs-burst(Jobs, Burst, Collections, Math) ·dots-physics(Physics) ·dots-graphics(Rendering).
When This Skill Triggers
Section titled “When This Skill Triggers”- Writing
IComponentData,ICleanupComponentData,IEnableableComponent,ISharedComponentData,IBufferElementData - Implementing
ISystemorSystemBasesystems - Using
SystemAPI.Query,SystemAPI.GetComponent,SystemAPI.GetSingleton - Creating
Baker(T)authoring components or baking systems - Using
EntityCommandBuffer,EntityManager,EntityQuery - Writing
IJobEntityjobs with ECS - Setting up
LocalTransform, parent/child hierarchies - Configuring system ordering, update groups, custom worlds
Quick Reference
Section titled “Quick Reference”| Task | Reference File |
|---|---|
| IComponentData, tags, ICleanupComponentData, IEnableableComponent | components-guide.md |
| ISharedComponentData, Chunk Components, DynamicBuffer | buffers-shared-guide.md |
| ISystem, SystemBase, SystemAPI.Query | systems-guide.md |
| EntityQuery builder, system ordering, update groups | query-ordering-guide.md |
| Worlds, bootstrap, custom worlds, IAspect (deprecated) | worlds-aspect-guide.md |
| EntityManager, EntityCommandBuffer, structural changes, ECB parallel writer | entities-ecb-guide.md |
| Baker, authoring MonoBehaviour, subscenes, baking systems, blob assets in baker | baking-guide.md |
| LocalTransform, parent/child hierarchy, TransformUsageFlags | transforms-guide.md |
| IJobEntity scheduling, parallel writer, query filtering | jobs-guide.md |
| Advanced system patterns, system state, singleton patterns | systems-advanced-guide.md |
| IEnableableComponent pattern, LINQ policy, performance priority | patterns-guide.md |
| Editor utils: UnitArchetypeConfig, UnitAttackType, UnitPrefabUtility, CsvReader | editor-utilities-guide.md |
| EventCleanupHelper — generic ClearBuffer / DisableEnableable for one-frame events | event-cleanup-helper-guide.md |
| CooldownTimer / CooldownTimerSystem / ICooldownState — countdown timer pattern | cooldown-timer-guide.md |
| Lifetime / LifetimeSystem / DeadTagLifetimeSystem — auto-destroy countdown + dead-entity bridge | lifetime-guide.md |
| TargetEntity / TargetSelector / SelectNearestTargetSystem — generic target selection | targeting-guide.md |
| RespawnResetHelper — standard respawn-ready query builder | respawn-reset-helper-guide.md |
| DirtyTag — generic enableable dirty/recalculate signal (replaces StatsDirtyTag etc.) | dirty-tag-guide.md |
| TeamId — canonical team affiliation component (SSOT) | team-id-guide.md |
| Shared Burst primitives — GridMath, StatMath.Ratio, WeightedSampler, CooldownTickHelper, DeterministicRandom (dots-core SSOT) | shared-burst-primitives.md |
Documentation
Section titled “Documentation”- Entities Manual
- Entities API
- Entities 1.4.5 Changelog
- ECS Samples
- Context7 library:
/needle-mirror/com.unity.entities(1187 snippets, High reputation, score 82.4)
Anti-Patterns for Cross-Project Reusability
Section titled “Anti-Patterns for Cross-Project Reusability”| Anti-Pattern | Symptom | Fix |
|---|---|---|
| God component | 10+ fields, multiple concerns | Split: Config + State + Stacking (e.g., a large stats component → 3 focused components) |
| Factory switch system | switch(enumType) with 3+ cases | Tag dispatch: separate systems per tag |
| God orchestrator module | Asmdef references ALL other modules | Per-module cleanup triggered by shared signal tag |
| Embedded component | Component defined inside system file | One type per file, in Components/ folder |
| Cross-module enum | Enum in Module A, used by Module B+C | Move to shared Core module (e.g., DamageType, CCType) |
| Mixed constants | Visual + combat + physics in one class | Split per domain: CombatConstants, VisualConstants, PhysicsLayerConfig |
| Boolean config state | Respawn.Enabled boolean | Use IEnableableComponent (RespawnConfig now toggleable) |
| Monolithic respawn | Single system resets all state | Per-module resets + RespawnReadyTag bridge (atomic module cleanup) |
| Visual transform feedback loop | PresentationSystemGroup modifies Position each frame → simulation reads modified value next frame → positions collapse exponentially | Save/restore pattern: store canonical value in dedicated component (e.g., SideViewGameZ) → restore at SimulationSystemGroup OrderFirst → simulate on canonical data → remap in PresentationSystemGroup |
See: dots-architecture/references/atomicity-guide.md for full audit checklist.
→ See references/patterns-guide.md for IEnableableComponent pattern, LINQ policy, and performance priority rules.
Key Conventions
Section titled “Key Conventions”Namespace layout convention:
[YourProject]— root[YourProject].Components— IComponentData structs[YourProject].Systems— ISystem structs[YourProject].Authoring— MonoBehaviour + Baker(T)[YourProject].Jobs— IJobEntity structs[YourProject].Physics— physics components and systems[YourProject].Rendering— rendering components and material overrides
Package versions:
com.unity.entities1.4.5com.unity.burst1.8.28com.unity.collections2.6.5com.unity.mathematics1.3.2com.unity.entities.graphics1.4.18
Critical rules:
- To use Burst on an ISystem, mark both the struct and each method
[BurstCompile], and make the structpartial - To defer structural changes inside a job, use
EntityCommandBuffer.ParallelWriterwith[ChunkIndexInQuery]sort key - To enable/disable a component without archetype moves, implement both
IComponentDataandIEnableableComponent - NEVER use
GetSingletonEntity<T>(),HasSingleton<T>(), orTryGetSingletonEntity<T>()onIEnableableComponenttypes — throwsInvalidOperationException. UseSystemAPI.Query<RefRW<T>>().WithPresent<T>().WithEntityAccess()instead - To bake a moving entity, pass
TransformUsageFlags.DynamictoGetEntity()in the Baker - To build large read-only shared data, use
BlobAssetand register viabaker.AddBlobAsset() - To detect entity destruction, use
ICleanupComponentData— it survivesDestroyEntityuntil explicitly removed
→ See references/gotchas-structural.md for stale cache after type changes, SetComponentEnabled structural change gotcha, two-pass pattern, and the default (uninitialized) EntityQuery NRE (guard .IsEmpty/.CalculateEntityCount() with query.IsCreated).
Event Communication
Section titled “Event Communication”Three patterns for one-frame inter-system events:
- IEnableableComponent (
*Event/*DirtyTag) — stateless signals, no payload. Cleanup system disables via IJobEntity at OrderFirst. - DynamicBuffer per-entity (
*Event : IBufferElementData) — payloaded events scoped to one entity. Consumer or cleanup system callsbuffer.Clear(). - DynamicBuffer singleton (
EntityEvent) — global cross-system queue withEntityEventTypediscriminator. Cleared byCoreEventCleanupSystem.
Cross-assembly gotcha: IJobEntity in a cleanup system MUST live in the same assembly as the event component type. Cross-assembly job definitions cause Burst source generation job safety errors.
→ Full patterns, checklist, and cleanup system map: dots-rpg/references/event-conventions.md
Addressables-First (library v2.0.0+)
Section titled “Addressables-First (library v2.0.0+)”Since unity-dots-library v2.0.0 (2026-05-23) all prefab fields in library bakers + demo authoring use AssetReferenceGameObject, not raw GameObject. The bake helper is AssetReferenceBakerExtensions.BakeAssetReference(...) (SSOT in com.the1studio.dots-core).
- Runtime-asmdef bans (enforced by
AddressablesEnforcementTests): noResources.Load(, noAssetDatabase.LoadAssetAtPath, noObject.Instantiate(GameObject)outside the per-project allowlist. ECS-sideEntityManager.Instantiate(Entity)andecb.Instantiate(Entity)are fine — different overload, different target. - In a Baker, never call
GetEntity(prefab)directly on anAssetReferenceGameObject. Use the helper — it handles the weak-reference indirection and produces a baked Entity reference for runtime spawning.
→ See dots-architecture/references/addressables-pattern.md for the full authoring → baker → runtime flow.
Best Practices Audit Checklist (W4.4)
Section titled “Best Practices Audit Checklist (W4.4)”Every ISystem must satisfy all of the following before merge:
[BurstCompile]on struct AND onOnUpdate/OnCreate/OnDestroy— exception:OnCreatewith structural changes.[RequireMatchingQueriesForUpdate]on any system whose query may be empty at startup or in idle frames — BUT ONLY if the system registers at least one query (inlineSystemAPI.Query, IJobEntity scheduling, orOnCreateRequireForUpdate<T>). NEVER put RMQFU on a system whoseOnUpdateonly delegates to a static helper that builds its query internally (e.g.EventCleanupHelper.ClearBuffer<T>) — RMQFU sees zero registered queries and deadlocks:OnUpdatenever runs. Drop RMQFU and run unconditionally instead (the helper’sWithAll<T>makes the empty case a cheap no-op). Catastrophic, silent, no error. Caught in library412f905(13 dead cleanup systems). → full explanation: references/event-cleanup-helper-guide.md § “CATASTROPHIC GOTCHA”.- No
EntityManager.AddComponent/RemoveComponent/AddBuffer/DestroyEntityinOnUpdateloops — use ECB. ComponentLookup<T>andBufferLookup<T>cached inOnCreate, updated via.Update(ref state)eachOnUpdate— never created per-frame.ScheduleParalleljobs use[ChunkIndexInQuery]as ECB sort key — never raw entity index.
→ Full 38-pattern checklist with W4 baseline stats + T1/T7/T8/T11 guidance: references/best-practices.md
→ IEnableableComponent vs. DisabledTag decision guide: references/ienableable-vs-disabledtag.md
→ ComponentLookup/BufferLookup caching patterns: references/component-lookup-caching.md
→ ECB system selection, parallel writer, sort key gotchas: references/ecb-patterns.md
→ BlobAssetReference construction, baker registration, runtime lifetime: references/blob-assets.md
→ ISharedComponentData partitioning, uniqueness ceiling, chunk fragmentation: references/shared-components.md
→ SystemState vs. SystemAPI access pattern decision guide: references/system-state-vs-systemapi.md
→ Burst + source-gen gotchas — BC1028, OnCreate no-op, missing [BurstCompile] clusters, SGFE011 (open-generic DynamicBufferreferences/gotchas-burst.md
Related rules
Section titled “Related rules”rules/library-feature-discovery-protocol.md— research the library 3× before implementing new functionality; always update this skill with what you find (or with the new code if you implement it)rules/manual-correction-implies-skill-gap-unity.md— if you manually inject library/API knowledge into a teammate brief, that knowledge belongs in this skill, not the brief