[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6KG66X66AFVCFS558RRX9N3":3,"skill-same:01M6KG66X66AFVCFS558RRX9N3":67},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":37,"linkOnly":38,"markdownContent":39,"markdownBody":40,"frontMatter":41,"refName":46,"commitSha":47,"skillDirectory":48,"forksCount":49,"repositoryHtmlUrl":50,"repositoryHomepageUrl":6,"ownerHtmlUrl":51,"ownerBlogUrl":6,"ownerDescription":52,"updatedAt":53,"install":54,"resources":66},"01M6KG66X66AFVCFS558RRX9N3","icleanupcomponentdata-runtime",null,"React to entity destruction at runtime by attaching a cleanup component that survives DestroyEntity, allowing a system to detect destroyed entities, release associated resources, and finalise true ...","dyCuong03\u002Funity-agent-team","dyCuong03","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F137050365?v=4","01M6KFXC85HQHXZJC2VC1KY6EZ","CuongND","01M6KFXCCHP6CD5MTA8NECJC36",8,"MIT","https:\u002F\u002Fgithub.com\u002FdyCuong03\u002Funity-agent-team\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Funity-dots\u002Ficleanupcomponentdata-runtime\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],"icleanupcomponentdata runtime","runtime","structural","structural-change","entity","at","destruction","true","detect","resources","react","finalise","system","lifecycle","release","cleanup","component","change","2026-11-10 10:12:30",false,"﻿---\nname: icleanupcomponentdata-runtime\ndescription: React to entity destruction at runtime by attaching a cleanup component that survives DestroyEntity, allowing a system to detect destroyed entities, release associated resources, and finalise true ...\ntags: [structural-change, lifecycle]\nmetadata:\n  internal-only: true\n  tier: 3\n---\n\n# ICleanupComponentData — Runtime Entity Lifecycle\n\n## Intent\nReact to entity destruction at runtime by attaching a cleanup component that survives DestroyEntity, allowing a system to detect destroyed entities, release associated resources, and finalise true removal.\n\n## Use When\nAn entity owns external resources (GPU buffers, physics bodies, audio instances, spatial index entries, registry slots) that must be explicitly released when the entity is destroyed. Any system that needs an \"on-destroy\" callback pattern.\n\n## Avoid When\nThe entity has no associated resources requiring cleanup — cleanup components add chunk overhead for entities that don't need them. Do not use in the baking world without [BakingType] (see [[baking-type-cleanup-component]] for baking lifecycle tracking).\n\n## Senior Pattern\n- Declare `public struct MyCleanup : ICleanupComponentData { \u002F* resource handles *\u002F }`.\n- A setup system adds MyCleanup to entities when they are created (or when the resource is acquired).\n- DestroyEntity removes all non-cleanup components but keeps MyCleanup — the entity persists in a \"tombstone\" state.\n- Cleanup system query: `.WithAll\u003CMyCleanup>().WithNone\u003CMyMainComponent>()` — matches only destroyed entities.\n- Cleanup system: releases resource, then `ecb.RemoveComponent\u003CMyCleanup>(entity)` — triggers true entity destruction.\n\n## Code Template\n```csharp\npublic struct AudioInstanceCleanup : ICleanupComponentData\n{\n    public int AudioHandle;\n}\n\n\u002F\u002F Setup system — adds cleanup when audio entity is created\n[BurstCompile]\npublic partial struct AudioSetupSystem : ISystem\n{\n    public void OnUpdate(ref SystemState state)\n    {\n        var ecb = SystemAPI\n            .GetSingleton\u003CBeginSimulationEntityCommandBufferSystem.Singleton>()\n            .CreateCommandBuffer(state.WorldUnmanaged);\n\n        foreach (var (audio, entity) in\n            SystemAPI.Query\u003CRefRO\u003CAudioSource>>()\n                .WithNone\u003CAudioInstanceCleanup>()\n                .WithEntityAccess())\n        {\n            int handle = AcquireAudioHandle(audio.ValueRO.ClipId);\n            ecb.AddComponent(entity, new AudioInstanceCleanup { AudioHandle = handle });\n        }\n    }\n}\n\n\u002F\u002F Cleanup system — detects destroyed audio entities, releases resources\n[BurstCompile]\npublic partial struct AudioCleanupSystem : ISystem\n{\n    public void OnUpdate(ref SystemState state)\n    {\n        var ecb = SystemAPI\n            .GetSingleton\u003CBeginSimulationEntityCommandBufferSystem.Singleton>()\n            .CreateCommandBuffer(state.WorldUnmanaged);\n\n        \u002F\u002F WithNone\u003CAudioSource> = entity was destroyed (cleanup survived)\n        foreach (var (cleanup, entity) in\n            SystemAPI.Query\u003CRefRO\u003CAudioInstanceCleanup>>()\n                .WithNone\u003CAudioSource>()\n                .WithEntityAccess())\n        {\n            ReleaseAudioHandle(cleanup.ValueRO.AudioHandle);\n            ecb.RemoveComponent\u003CAudioInstanceCleanup>(entity);  \u002F\u002F triggers true destruction\n        }\n    }\n}\n```\n\n## Anti-Patterns\n- Query `.WithAll\u003CMyCleanup, MyMainComponent>()` — matches live entities, not destroyed ones. Correct pattern is WithNone\u003CMainComponent>.\n- Forgetting to RemoveComponent\u003CMyCleanup> after processing — entity persists forever as a tombstone, chunk space permanently consumed.\n- Adding cleanup without a corresponding system to remove it — permanent entity leak.\n- Using ICleanupComponentData for state that should be handled by ECB DestroyEntity alone — unnecessary complexity.\n\n## Runtime Risks\n- Missing cleanup removal: entity never truly destroys, archetype chunk fills with tombstones over time, memory leak.\n- Wrong query (WithAll instead of WithNone on main component): processes live entities as if they're destroyed, incorrect resource release.\n\n## Performance Notes\nTombstone entities occupy chunk space from DestroyEntity until cleanup removal. In high-entity-count games with frequent destruction, delayed cleanup accumulates. Always process and remove cleanup in the same frame it's detected.\n\n## Architecture Guidance\nICleanupComponentData is the ECS equivalent of a destructor. Use it deliberately — only for entities with genuine resource associations. Keep the cleanup component lean (just the handles needed for release). The setup + tombstone + cleanup pattern is a three-system lifecycle: acquire → use → release.\n\n## Related Skills\n[[entity-command-buffer]], [[ecb-system-timing]], [[baking-type-cleanup-component]]\n","# ICleanupComponentData — Runtime Entity Lifecycle\n\n## Intent\nReact to entity destruction at runtime by attaching a cleanup component that survives DestroyEntity, allowing a system to detect destroyed entities, release associated resources, and finalise true removal.\n\n## Use When\nAn entity owns external resources (GPU buffers, physics bodies, audio instances, spatial index entries, registry slots) that must be explicitly released when the entity is destroyed. Any system that needs an \"on-destroy\" callback pattern.\n\n## Avoid When\nThe entity has no associated resources requiring cleanup — cleanup components add chunk overhead for entities that don't need them. Do not use in the baking world without [BakingType] (see [[baking-type-cleanup-component]] for baking lifecycle tracking).\n\n## Senior Pattern\n- Declare `public struct MyCleanup : ICleanupComponentData { \u002F* resource handles *\u002F }`.\n- A setup system adds MyCleanup to entities when they are created (or when the resource is acquired).\n- DestroyEntity removes all non-cleanup components but keeps MyCleanup — the entity persists in a \"tombstone\" state.\n- Cleanup system query: `.WithAll\u003CMyCleanup>().WithNone\u003CMyMainComponent>()` — matches only destroyed entities.\n- Cleanup system: releases resource, then `ecb.RemoveComponent\u003CMyCleanup>(entity)` — triggers true entity destruction.\n\n## Code Template\n```csharp\npublic struct AudioInstanceCleanup : ICleanupComponentData\n{\n    public int AudioHandle;\n}\n\n\u002F\u002F Setup system — adds cleanup when audio entity is created\n[BurstCompile]\npublic partial struct AudioSetupSystem : ISystem\n{\n    public void OnUpdate(ref SystemState state)\n    {\n        var ecb = SystemAPI\n            .GetSingleton\u003CBeginSimulationEntityCommandBufferSystem.Singleton>()\n            .CreateCommandBuffer(state.WorldUnmanaged);\n\n        foreach (var (audio, entity) in\n            SystemAPI.Query\u003CRefRO\u003CAudioSource>>()\n                .WithNone\u003CAudioInstanceCleanup>()\n                .WithEntityAccess())\n        {\n            int handle = AcquireAudioHandle(audio.ValueRO.ClipId);\n            ecb.AddComponent(entity, new AudioInstanceCleanup { AudioHandle = handle });\n        }\n    }\n}\n\n\u002F\u002F Cleanup system — detects destroyed audio entities, releases resources\n[BurstCompile]\npublic partial struct AudioCleanupSystem : ISystem\n{\n    public void OnUpdate(ref SystemState state)\n    {\n        var ecb = SystemAPI\n            .GetSingleton\u003CBeginSimulationEntityCommandBufferSystem.Singleton>()\n            .CreateCommandBuffer(state.WorldUnmanaged);\n\n        \u002F\u002F WithNone\u003CAudioSource> = entity was destroyed (cleanup survived)\n        foreach (var (cleanup, entity) in\n            SystemAPI.Query\u003CRefRO\u003CAudioInstanceCleanup>>()\n                .WithNone\u003CAudioSource>()\n                .WithEntityAccess())\n        {\n            ReleaseAudioHandle(cleanup.ValueRO.AudioHandle);\n            ecb.RemoveComponent\u003CAudioInstanceCleanup>(entity);  \u002F\u002F triggers true destruction\n        }\n    }\n}\n```\n\n## Anti-Patterns\n- Query `.WithAll\u003CMyCleanup, MyMainComponent>()` — matches live entities, not destroyed ones. Correct pattern is WithNone\u003CMainComponent>.\n- Forgetting to RemoveComponent\u003CMyCleanup> after processing — entity persists forever as a tombstone, chunk space permanently consumed.\n- Adding cleanup without a corresponding system to remove it — permanent entity leak.\n- Using ICleanupComponentData for state that should be handled by ECB DestroyEntity alone — unnecessary complexity.\n\n## Runtime Risks\n- Missing cleanup removal: entity never truly destroys, archetype chunk fills with tombstones over time, memory leak.\n- Wrong query (WithAll instead of WithNone on main component): processes live entities as if they're destroyed, incorrect resource release.\n\n## Performance Notes\nTombstone entities occupy chunk space from DestroyEntity until cleanup removal. In high-entity-count games with frequent destruction, delayed cleanup accumulates. Always process and remove cleanup in the same frame it's detected.\n\n## Architecture Guidance\nICleanupComponentData is the ECS equivalent of a destructor. Use it deliberately — only for entities with genuine resource associations. Keep the cleanup component lean (just the handles needed for release). The setup + tombstone + cleanup pattern is a three-system lifecycle: acquire → use → release.\n\n## Related Skills\n[[entity-command-buffer]], [[ecb-system-timing]], [[baking-type-cleanup-component]]\n",{"name":5,"tags":42,"metadata":43,"description":7},[22,32],{"tier":44,"internal-only":45},3,true,"main","fe4746b9f07e6c7c2b6d3932002183af9b9f6fa2",".claude\u002Fskills\u002Funity-dots\u002Ficleanupcomponentdata-runtime",0,"https:\u002F\u002Fgithub.com\u002FdyCuong03\u002Funity-agent-team","https:\u002F\u002Fgithub.com\u002FdyCuong03","Game developer","2026-07-25 22:22:25",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":45},[56,59,62],{"tool":57,"command":58},"npx","npx skills add dyCuong03\u002Funity-agent-team --skill icleanupcomponentdata-runtime",{"tool":60,"command":61},"bunx","bunx skills add dyCuong03\u002Funity-agent-team --skill icleanupcomponentdata-runtime",{"tool":63,"command":64},"pnpm","pnpm dlx skills add dyCuong03\u002Funity-agent-team --skill icleanupcomponentdata-runtime","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FdyCuong03\u002Funity-agent-team\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Funity-dots\u002Ficleanupcomponentdata-runtime\u002FSKILL.md",[],[68,92,114,138,158,177],{"skillNo":69,"name":70,"nameZh":6,"description":71,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":37},"01M6KH55FFS00ET877QSMRYGX4","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 \u002F SimulationSystemGroup \u002F PresentationSystemGroup \u002F FixedStepSimulationSystemGroup \u002F VariableRateSimulationSystemGroup, UpdateBefore \u002F UpdateAfter peer ordering, OrderFirst \u002F 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.","https:\u002F\u002Fgithub.com\u002FdyCuong03\u002Funity-agent-team\u002Fblob\u002Fmain\u002Fworkspace\u002Fdots-program\u002Fscratch\u002Fwave-2-orchestrator-drafts\u002Fdots-update-groups\u002FSKILL.md",[],[75,76,77,78,79,31,80,81,82,83,84,85,86,87,88,89,90,91],"update","dots update groups","boundary","simulation","how","choose","work","use","never","peer","deterministic","how to","coupling","ecs","bugs","frame","value",{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":98,"publishedAt":37},"01M6KH50PWYEFQDCGYBZ0326F1","dots-transform-patterns","The Entities 1.x transform model — LocalTransform (writable input) vs LocalToWorld (system-owned matrix), Parent\u002FChild hierarchy, reparenting cost, uniform vs non-uniform scale (PostTransformMatrix), and when to opt out with custom transform systems. Use when designing parent\u002Fchild hierarchies, runtime reparenting (mount\u002Fdismount\u002Fsocket), or choosing transform components at the Baker boundary.","https:\u002F\u002Fgithub.com\u002FdyCuong03\u002Funity-agent-team\u002Fblob\u002Fmain\u002Fworkspace\u002Fdots-program\u002Fscratch\u002Fwave-2-orchestrator-drafts\u002Fdots-transform-patterns\u002FSKILL.md",[],[99,100,101,102,77,31,103,104,82,105,20,106,107,108,109,110,24,111,112,113],"patterns","transform","dots transform patterns","components","mount","model","cost","systems","input","with","matrix","socket","child","custom","hierarchy",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":118,"categories":119,"keywords":125,"publishedAt":37},"01M6KH4VW4MA14DQW4KQYPFT0S","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 \u002F GetSingletonRW \u002F HasSingleton \u002F 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.","https:\u002F\u002Fgithub.com\u002FdyCuong03\u002Funity-agent-team\u002Fblob\u002Fmain\u002Fworkspace\u002Fdots-program\u002Fscratch\u002Fwave-2-orchestrator-drafts\u002Fdots-singleton-patterns\u002FSKILL.md",[120],{"categoryNo":121,"categoryName":122,"taxonomyType":123,"taxonomyTypeDesc":124},"01JBSEEDCAT000000000000037","律师与法务","PROFESSION","适用职业",[99,126,127,35,128,129,130,31,104,82,131,132,133,20,134,135,108,90,136,137],"singleton","dots singleton patterns","config","state","game","writer","time","shared","contract","as","ecb","gating",{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":144,"publishedAt":37},"01M6KH4PR076AYNDZHD63HHWX6","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 \u002F 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\u002FUI must trigger ECS work.","https:\u002F\u002Fgithub.com\u002FdyCuong03\u002Funity-agent-team\u002Fblob\u002Fmain\u002Fworkspace\u002Fdots-program\u002Fscratch\u002Fwave-2-orchestrator-drafts\u002Fdots-hybrid-bridge\u002FSKILL.md",[],[145,146,147,148,102,129,77,149,150,81,151,152,82,20,153,154,107,155,156,157],"bridge","hybrid","dots hybrid bridge","mesh","assets","Rules","read","view","trigger","unity","material","for","managed",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":162,"categories":163,"keywords":164,"publishedAt":37},"01M6KH4FGRQ9AP2ND5H5HX4D83","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 \u002F UnityEvent \u002F static bus anti-patterns. Use when input\u002FUI\u002Fnetwork 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.","https:\u002F\u002Fgithub.com\u002FdyCuong03\u002Funity-agent-team\u002Fblob\u002Fmain\u002Fworkspace\u002Fdots-program\u002Fscratch\u002Fwave-2-orchestrator-drafts\u002Fdots-event-driven-ecs\u002FSKILL.md",[],[165,166,88,167,168,102,36,169,170,104,81,171,172,99,173,21,107,174,175,176],"event driven","driven","event","dots event driven ecs","ui","network","command","anti-patterns","pattern","events","static","request",{"skillNo":178,"name":179,"nameZh":6,"description":180,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":181,"categories":182,"keywords":194,"publishedAt":37},"01M6KH4BWRGCEBJ8PKCKCSGT33","valid_skill","A complete, well-formed test fixture skill for SkillHub validation testing. Covers basic task routing and code review for Unity projects.","https:\u002F\u002Fgithub.com\u002FdyCuong03\u002Funity-agent-team\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fvalid_skill\u002FSKILL.md",[183,188,191],{"categoryNo":184,"categoryName":185,"taxonomyType":186,"taxonomyTypeDesc":187},"01JBSEEDCAT000000000000007","代码审查","SCENARIO","使用场景",{"categoryNo":189,"categoryName":190,"taxonomyType":186,"taxonomyTypeDesc":187},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":192,"categoryName":193,"taxonomyType":186,"taxonomyTypeDesc":187},"01JBSEEDCAT000000000000023","Skill与智能体开发",[195,196,197,198,199,200,201,202,203,204,205,206,207,208,154,209,156],"valid skill","valid","code review","testing","review","test","routing","code","validation","projects","fixture skill","task","fixture","basic","complete"]