Unity Collection Pool expert for GC-free collection management using ListPool, DictionaryPool, HashSetPool, and ObjectPool. Masters memory optimization, pool sizing, and allocation-free patterns. Use PROACTIVELY for collection allocations, GC pressure reduction, temporary list/dictionary usage, or performance-critical code paths.
/plugin marketplace add creator-hian/claude-code-plugins/plugin install unity-plugin@creator-hian-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/advanced-patterns.mdreferences/pool-fundamentals.mdUnity's UnityEngine.Pool namespace (2021.1+) provides built-in collection pooling to eliminate GC allocations from temporary collection usage.
Foundation Required: unity-csharp-fundamentals (TryGetComponent, FindAnyObjectByType), C# generics, IDisposable pattern
Core Topics:
using UnityEngine.Pool;
using System.Collections.Generic;
public class PoolExample : MonoBehaviour
{
void ProcessItems()
{
// Get pooled list (zero allocation after warmup)
List<int> tempList = ListPool<int>.Get();
try
{
// Use the list
tempList.Add(1);
tempList.Add(2);
tempList.Add(3);
ProcessList(tempList);
}
finally
{
// Always return to pool
ListPool<int>.Release(tempList);
}
}
}
using UnityEngine.Pool;
void ProcessWithUsing()
{
// Auto-release via PooledObject<T>
List<int> tempList;
using (ListPool<int>.Get(out tempList))
{
tempList.Add(1);
tempList.Add(2);
DoSomething(tempList);
} // Automatically returned to pool
}
// HashSet example
void CheckDuplicates(IEnumerable<string> items)
{
HashSet<string> seen;
using (HashSetPool<string>.Get(out seen))
{
foreach (string item in items)
{
if (!seen.Add(item))
Debug.Log($"Duplicate: {item}");
}
}
}
// Dictionary example
void BuildLookup(Item[] items)
{
Dictionary<int, Item> lookup;
using (DictionaryPool<int, Item>.Get(out lookup))
{
foreach (Item item in items)
lookup[item.Id] = item;
ProcessLookup(lookup);
}
}
| Pool Type | Usage | Get/Release |
|---|---|---|
ListPool<T> | Temporary lists | Get() / Release(list) |
HashSetPool<T> | Duplicate checking, set operations | Get() / Release(set) |
DictionaryPool<K,V> | Temporary lookups | Get() / Release(dict) |
CollectionPool<C,T> | Custom ICollection types | Get() / Release(coll) |
ObjectPool<T> | Arbitrary object pooling | Get() / Release(obj) |
LinkedPool<T> | Linked list-based pool | Get() / Release(obj) |
GenericPool<T> | Static shared pool | Get() / Release(obj) |
void DetectCollisions(Vector3 origin, Vector3 direction)
{
List<RaycastHit> hits;
using (ListPool<RaycastHit>.Get(out hits))
{
int count = Physics.RaycastNonAlloc(origin, direction, hitsArray);
for (int i = 0; i < count; i++)
hits.Add(hitsArray[i]);
ProcessHits(hits);
}
}
void FindAllEnemies()
{
List<Enemy> enemies;
using (ListPool<Enemy>.Get(out enemies))
{
GetComponentsInChildren(enemies); // Overload that takes list
foreach (Enemy enemy in enemies)
enemy.Alert();
}
}
// AVOID: LINQ allocates
List<Item> filtered = items.Where(x => x.IsActive).ToList();
// PREFER: Pooled collection
List<Item> pooledFiltered;
using (ListPool<Item>.Get(out pooledFiltered))
{
foreach (Item item in items)
{
if (item.IsActive)
pooledFiltered.Add(item);
}
Process(pooledFiltered);
}
Use Pools:
- Temporary collections in Update/FixedUpdate
- Collections created and discarded within single method
- High-frequency operations (per-frame, per-physics-step)
- Known short-lived collection usage
Avoid Pools:
- Long-lived collections (store as fields instead)
- Collections passed across async boundaries
- Collections with unclear ownership
- Very small operations (< 3 items, consider stackalloc)
// For very small, fixed-size arrays, prefer stackalloc
Span<int> small = stackalloc int[4];
// For variable size or larger collections, use pool
List<int> larger;
using (ListPool<int>.Get(out larger))
{
// Variable size operations
}
using pattern or try/finally to guarantee releaseusing Pattern: Auto-disposal prevents leaks// WRONG: Storing pooled reference
private List<int> mCachedList;
void Bad()
{
mCachedList = ListPool<int>.Get(); // Memory leak!
}
// WRONG: Missing release
void AlsoBAD()
{
List<int> list = ListPool<int>.Get();
Process(list);
// Forgot to release - leak!
}
// WRONG: Releasing wrong pool
void VeryBad()
{
List<int> list = ListPool<int>.Get();
ListPool<float>.Release(list); // Type mismatch!
}
// WRONG: Using after release
void TerriblyBad()
{
List<int> list;
using (ListPool<int>.Get(out list)) { }
list.Add(1); // Using disposed collection!
}
Core pool concepts:
Advanced usage patterns:
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.