wave7-idisposable-managed-component
Safely release unmanaged or native resources held by a managed IComponentData when the component is removed or the entity is destroyed.
- License 许可
- MIT
- 最近更新
- 2026-07-25
- Stars
- ★ 8
- Forks
- 0
01 前言 Front Matter
- name
- wave7-idisposable-managed-component
- tags
- [ "hybrid", "managed", "lifecycle" ]
- metadata
- { "tier": 3, "internal-only": true }
- description
- Safely release unmanaged or native resources held by a managed IComponentData when the component is removed or the entity is destroyed.
03 SKILL.md 正文
IDisposable Managed Component — Native Resource Cleanup
Intent
Safely release unmanaged or native resources held by a managed IComponentData when the component is removed or the entity is destroyed.
Use When
- Your class IComponentData holds NativeArray, NativeList, or other IDisposable resources that must be freed
- Native resources must be explicitly freed before structural change (RemoveComponent, DestroyEntity)
Avoid When
- The component holds only managed .NET objects with their own GC lifecycle — IDisposable is unnecessary overhead
- The native resource lifetime is managed externally (e.g., WorldUpdateAllocator) — no manual Dispose needed
Senior Pattern
public class NativeDataComponent : IComponentData, IDisposable
{
public NativeArray<float> Buffer;
public void Dispose()
{
if (Buffer.IsCreated) Buffer.Dispose();
}
}
// CORRECT — Dispose before removing:
entityManager.GetComponentObject<NativeDataComponent>(entity).Dispose();
entityManager.RemoveComponent<NativeDataComponent>(entity);
// CORRECT — Dispose before destroy (use cleanup system pattern):
[UpdateInGroup(typeof(InitializationSystemGroup))]
public partial class NativeDataCleanupSystem : SystemBase
{
protected override void OnUpdate()
{
var ecb = new EntityCommandBuffer(Allocator.Temp);
// PendingDestroy tag signals intent to destroy:
foreach (var (nativeData, entity) in
SystemAPI.Query<NativeDataComponent>()
.WithAll<PendingDestroy>()
.WithEntityAccess())
{
nativeData.Dispose();
ecb.DestroyEntity(entity);
}
ecb.Playback(EntityManager);
ecb.Dispose();
}
}
Anti-Patterns
- Removing the component without calling Dispose — native memory leak; no automatic ECS lifecycle hook calls Dispose.
- Relying on the GC to call Dispose — GC finalizers are not guaranteed to run; and NativeArray leak detection fires immediately.
- Storing a managed component with native resources without IDisposable — leak is undetectable until native memory exhaustion.
- Calling Dispose inside a job — managed component Dispose must run on the main thread.
Runtime Risks
- Native memory leak if Dispose is not called explicitly before structural change — Unity's leak detection will flag this in development builds.
- No automatic ECS lifecycle hook calls Dispose — the developer must arrange cleanup explicitly.
- If entity is destroyed via DestroyEntity without Dispose, the GC will eventually collect the class but the NativeArray inside will leak permanently.
Performance Notes
- Disposal is a one-time cost. The risk is leak accumulation over session lifetime, not per-frame cost.
- NativeArray.IsCreated guard before Dispose prevents double-free; always include it.
Architecture Guidance
- Canonical pattern: add a
PendingDestroytag component; cleanup system queriesWithAll<PendingDestroy>, calls Dispose, then ECB.DestroyEntity. - Alternatively use ICleanupComponentData to guarantee cleanup runs even after ECS entity destruction — see icleanupcomponentdata-runtime.md.
- Document every NativeDataComponent field with the responsible owner for Dispose — prevents cross-system confusion.
Related Skills
[[managed-component-bridge]], [[icleanupcomponentdata-runtime]], [[wave7-companion-go-lifecycle]], [[wave4-world-update-allocator-per-frame-native]]
04 同仓库更多 Skills
dots-update-groups
How to choose the right ECS system group and ordering so per-frame and per-fixed-step work is deterministic and never races its own readers. Covers InitializationSystemGroup / SimulationSystemGroup / PresentationSystemGroup / FixedStepSimulationSystemGroup / VariableRateSimulationSystemGroup, UpdateBefore / UpdateAfter peer ordering, OrderFirst / OrderLast group-boundary placement, RateManager, and the cross-group ordering trap. Use when adding an ISystem, fixing "value visible one frame late" bugs, or coupling simulation to a fixed timestep.
dots-transform-patterns
The Entities 1.x transform model — LocalTransform (writable input) vs LocalToWorld (system-owned matrix), Parent/Child hierarchy, reparenting cost, uniform vs non-uniform scale (PostTransformMatrix), and when to opt out with custom transform systems. Use when designing parent/child hierarchies, runtime reparenting (mount/dismount/socket), or choosing transform components at the Baker boundary.
dots-singleton-patterns
Model cross-system shared configuration and game state as a single-entity component with a strict single-writer contract. Covers RequireForUpdate gating, SystemAPI.GetSingleton / GetSingletonRW / HasSingleton / TryGetSingleton, bake-time vs runtime-created vs ECB-system singletons, the "exactly one entity" runtime invariant, and the single-writer rule. Use when designing frame-stable global config, shared mutable state, or any component intended to exist on exactly one entity.
dots-hybrid-bridge
The one-way bridge between DOTS-owned runtime state and Unity-owned presentation. Covers UnityObjectRef for managed asset refs in components, the DOTS-writes / Unity-reads ownership rule, when to use managed IComponentData vs UnityObjectRef vs CompanionComponent, baker-bridge vs runtime-bridge, and SubScene boundary rules. Use when an entity must reference Unity assets (Mesh, Material, AudioClip, ScriptableObject), a MonoBehaviour view must read entity state, or input/UI must trigger ECS work.
dots-event-driven-ecs
Model one-frame events and external requests in ECS without dual ownership, polling, or persistent state leaks. Covers request-tag pattern with ECB, enableable command components (no structural change), event buffers (IBufferElementData), explicit consumer ownership, one-frame latency rules, and the banned C# event / UnityEvent / static bus anti-patterns. Use when input/UI/network must trigger ECS work, when a one-frame signal fans out to N consumers (damage, hit, collision), or when state changes must be processed exactly once.
valid_skill
A complete, well-formed test fixture skill for SkillHub validation testing. Covers basic task routing and code review for Unity projects.