Quick answer: Unity Addressables holding loaded assets in memory after use? Each AsyncOperationHandle increments the asset’s ref count. Without Addressables.Release(handle), the asset never unloads.
Loading 50 different addressable prefabs over a play session causes memory to balloon. Handles aren’t released; ref counts stay at 1.
Reference-Counted Lifecycle
Every LoadAssetAsync, InstantiateAsync, etc. returns a handle that holds a reference. The asset stays in memory until the matching Release drops the count to 0.
Release Pattern
AsyncOperationHandle<GameObject> h = Addressables.LoadAssetAsync<GameObject>(key);
await h.Task;
useAsset(h.Result);
Addressables.Release(h);Release when done. Storing many handles? Track them in a list, release in OnDestroy.
InstantiateAsync vs Instantiate
Use Addressables.InstantiateAsync for tracked spawns; ReleaseInstance on destroy. Pure GameObject.Instantiate after a load decouples from the addressable lifecycle — not what you want here.
Auto-Release Helpers
Wrap handle access in a tiny disposable: using var ah = new ManagedHandle(key); — Dispose releases. Saves remembering Release everywhere.
Verifying
Memory profiler shows asset bundle unload after the matching releases. No leaks across spawn/destroy cycles.
“Each Load increments ref count. Release every handle when done.”
Track addressable handles in CI memory tests — leaks compound across hours; tests catch the pattern early.