t1k:unity:dots-core:performance
| Field | Value |
|---|---|
| Module | dots-core |
| Version | 2.3.2 |
| Effort | medium |
| Tools | — |
Keywords: DOTS, optimization, performance, profiling
How to invoke
Section titled “How to invoke”/t1k:unity:dots-core:performanceDOTS Performance Optimization
Section titled “DOTS Performance Optimization”Coding patterns: see
/dots-ecs(Performance Priority section). Job specifics: see/dots-jobs-burst. Draw calls / batching: see/dots-graphics(RenderMeshArray, SRP Batcher, GPU instancing).Context7 sources:
/needle-mirror/com.unity.entities(query optimization),/needle-mirror/com.unity.burst(Burst best practices),/websites/unity3d_packages_com_unity_collections_2_6(collection perf).
Rule #1 — Measure First
Section titled “Rule #1 — Measure First”Never optimize without data. Profile → identify → fix → verify.
IMPORTANT: rendering_stats is NOT a direct MCP tool. Call via batch_execute: batch_execute(commands=[{"tool":"rendering_stats","params":{"action":"get_stats"}}])
1. rendering_stats(get_stats) → FPS, draw calls, batches2. rendering_stats(get_memory) → mono heap, graphics driver, reserved3. rendering_stats(get_system_stats, top_n=30) → per-DOTS-system CPU breakdown (avg/max/p95/% frame)4. identify the ONE worst bottleneck5. fix it, re-profile, confirm improvementPost-Session Analysis (No Play Mode Required)
Section titled “Post-Session Analysis (No Play Mode Required)”Sessions auto-save as JSON on Play exit → Logs/PerfSessions/perf-YYYYMMDD-HHmmss.json.
1. rendering_stats(list_sessions) → list saved session files2. rendering_stats(analyze_session, → bottleneck report: HIGH/MEDIUM filename="perf-YYYYMMDD-HHmmss.json") severity issues, top 30 systemsSession JSON contains: FPS avg/min/max/p95, CPU avg/min/max/p95, top 30 systems by CPU, 500-point timeline, scene name, duration, peak entity count.
Regression workflow: record baseline session → implement optimization → record again → analyze_session both → compare top-system rankings.
→ See profiling-workflow-guide.md for step-by-step post-session workflow.
Reference Guides
Section titled “Reference Guides”| Topic | File | Coverage |
|---|---|---|
| MCP profiling workflow | profiling-workflow-guide.md | Live MCP steps, post-session analysis, verification checklist, mandatory reporting |
| Parallelization & queries | parallelization-guide.md | Job decision tree, SystemAPI random access fix, query optimization, Burst tips |
| Navigation performance | navigation-perf-guide.md | Nav scaling, dead agent cleanup, tier throttling, FixedStep, NavMesh gotchas |
| Memory & collections | memory-patterns-guide.md | Anti-patterns, SharedStatic, SpatialHash, chunk utilization, InternalBufferCapacity |
Draw Call Reduction
Section titled “Draw Call Reduction”SRP Batcher (free, always-on for URP):
- Requires all objects share the same shader variant
- Anti-pattern:
MaterialPropertyBlockper-instance disables SRP Batcher
GPU Instancing via ECS:
RenderMeshArray+MaterialMeshInfoenable automatic instancing- Each unique (mesh, material, layer) = separate draw call bucket — minimize combinations
- Tag components that change render state (color, emission) must use
MaterialPropertyattribute
Static batching for terrain/walls:
- Walls use per-segment LODGroup with impostor billboard at LOD1 — no mesh combining needed
- Do NOT combine meshes that need individual LODGroups or physics colliders
Transparent materials cause per-entity draw calls (CRITICAL): URP entities with _SURFACE_TYPE_TRANSPARENT get DepthSorted_Tag from Entities Graphics, forcing per-entity back-to-front rendering. This defeats SRP Batcher AND GPU instancing. Fix: Use AlphaTest (cutout) with _AlphaClip=1 + _Cutoff=0.5 instead of Transparent for sprites/quads. Only use Transparent for genuinely semi-transparent effects (particles, AoE blasts). In BattleDemo2D this reduced 608 to 28 batches (95.4%).
Key Anti-Patterns Summary
Section titled “Key Anti-Patterns Summary”| Anti-Pattern | Fix | Reference |
|---|---|---|
| Optimizing without profiling | Measure First (Rule #1) | This file |
SystemAPI.GetComponent in foreach | Cache ComponentLookup<T> in OnCreate | parallelization-guide.md |
| Allocating NativeList per entity per frame | Hoist before foreach, Clear each iteration | memory-patterns-guide.md |
| Dead agents processing through all nav systems | DeadAgentStopSystem disables NavMeshPath | navigation-perf-guide.md |
| AIUpdateTierSystem counting allies for distance | Filter by team in distance checks | navigation-perf-guide.md |
| Transparent materials on sprites | Use AlphaTest (cutout) instead | This file |
| Optimizing without saving a report | Always save to plans/reports/ | profiling-workflow-guide.md |