| name | memory-safety |
| description | Native container lifetime, allocator selection, and GC-avoidance rules for DOTS runtime code. Covers NativeArray/NativeList/NativeHashMap disposal patterns, Allocator.Temp vs TempJob vs Persistent guidance, and managed-allocation detection. Replaces the memory-checker subagent. |
| use-when | Load for unity-dots-dev when task involves NativeContainers, custom allocators,
native memory disposal, GC pressure investigation, or diagnosing AtomicSafetyHandle
/ InvalidOperationException on containers.
|
| do-not-use-when | Do not load for Unity classic MonoBehaviour tasks. Do not load for tester, verifier,
or data-tool roles. Not needed if the task touches no native memory or containers.
|
| platforms | ["claude-code","codex","copilot","cursor","windsurf"] |
| task-categories | ["ecs","memory","native-containers","performance","dots"] |
| metadata | {"source":"https://docs.unity3d.com/Packages/com.unity.collections@2.4","version":"2.4.4","tier":1} |
Memory Safety
This is a skill pack, not an agent.
Allocator Decision Tree
Lifetime ≤ this frame, this scope → Allocator.Temp
Lifetime ≤ this job → Allocator.TempJob (dispose in job)
Lifetime spans frames (system state) → Allocator.Persistent (Dispose in OnDestroy)
Job allocates output for main thread → Allocator.TempJob
Asset/blob (read-only, long-lived) → BlobAssetReference<T> (no allocator)
Rule: every Allocator.Persistent allocation must have a matching Dispose()
in OnDestroy (for ISystem use state.Dispose-bound NativeArray/Lookup
fields). Otherwise the Job Safety System will leak across domain reloads.
Native Container Rules
- Never store a
NativeArray allocated inside OnCreate without
Disposing it in OnDestroy.
- Never pass a
NativeArray to a job and reuse it on the main thread the
same frame unless the job is .Complete()d first (= sync point — requires
approval).
- Never resize a
NativeList from a parallel job. Use
NativeList<T>.ParallelWriter.
- Don't share writable native containers across two parallel jobs without
dependency chaining. The Safety System will flag it as
InvalidOperationException in editor; in player builds it silently corrupts.
NativeHashMap<K,V> is not parallel-safe for writes. Use
NativeParallelHashMap<K,V>.ParallelWriter for writes from multiple threads.
Managed Allocation Hotspots
These are silent GC bombs inside OnUpdate / hot paths. Audit before signaling
verifier:
| Anti-pattern | Replace with |
|---|
string.Format(...) / $"..." | FixedString*N*Bytes or skip the log |
new List<T>() | NativeList<T>(Allocator.Temp) |
LINQ (.Where, .Select, .ToList) | manual loop or IJobEntity |
Enum.GetValues(typeof(...)) | a cached static readonly array outside hot path |
Boxing (e.g. object o = someStruct;) | keep the type concrete |
Dictionary<K,V>.Add in hot path | NativeParallelHashMap<K,V> |
Debug.Log("…" + obj) | guard with #if UNITY_EDITOR if needed at all |
Blob Assets
Use BlobAssetReference<T> for read-only, long-lived data (terrain LUTs,
ability defs, item tables):
- Build with
BlobBuilder once, in a baker or [CreateAsset] flow.
- Pass by
BlobAssetReference<T> field on a component.
- Never mutate after build — blobs are immutable.
Pre-Verifier Checklist
Profiler Evidence (recommended)
If complexity ≥ medium and triage flagged this as a hot system: take a
GC Alloc sample before and after via profiler_get_runtime_memory and include
the delta in verification_bundle.logs_to_inspect.