AGENT SKILL

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 PendingDestroy tag component; cleanup system queries WithAll<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

dyCuong03
dyCuong03/unity-agent-team

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.

★ 8
dyCuong03
dyCuong03/unity-agent-team

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.

★ 8
dyCuong03
dyCuong03/unity-agent-team

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.

律师与法务
★ 8
dyCuong03
dyCuong03/unity-agent-team

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.

★ 8
dyCuong03
dyCuong03/unity-agent-team

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.

★ 8
dyCuong03
dyCuong03/unity-agent-team

valid_skill

A complete, well-formed test fixture skill for SkillHub validation testing. Covers basic task routing and code review for Unity projects.

代码审查测试与质量
★ 8