Quick answer: Addressables doesn’t support cancellation. Let loads complete then Addressables.Release(handle) to drop references and unload. Track handles to ensure release on scene exit.
A loading screen starts loading 50 assets via Addressables. Player presses Back to abort. The loads continue; memory grows; assets stay loaded forever because no Release ever fires.
No Cancel API
Addressables’ AsyncOperationHandle doesn’t expose Cancel. Loads run to completion. What you control is the reference: Release reduces the asset’s ref count; when it hits zero, Addressables unloads it.
The Pattern
List<AsyncOperationHandle> _handles = new();
public async Task LoadAll(string[] keys) {
foreach (var key in keys) {
var h = Addressables.LoadAssetAsync<object>(key);
_handles.Add(h);
}
foreach (var h in _handles) await h.Task;
}
public void AbortLoad() {
foreach (var h in _handles) {
if (h.IsValid()) Addressables.Release(h);
}
_handles.Clear();
}
Track every load. On abort, release all. Each Release decrements the asset’s ref count; when zero, the asset unloads. Memory returns to baseline.
SceneInstance Special Case
SceneInstance scene = await Addressables.LoadSceneAsync("Level1").Task;
// later:
await Addressables.UnloadSceneAsync(scene).Task;
Scenes use UnloadSceneAsync rather than Release. Forgetting to unload leaks the entire scene’s asset content.
Handle Validity
If a handle’s load is in progress and you Release, Addressables marks it for release; the asset never gets used. If the load already completed, Release decrements ref count. Check IsValid before Release if you might double-release.
Verifying
Profile memory through a load-abort cycle. Memory should return to baseline. If not, you have at least one unreleased handle — track every load source.
“Addressables loads can’t be canceled. Release the handle; let the load finish in the background. Memory reclaims after Release + GC.”
Centralize handle tracking in a LoadingManager singleton — ensures every Async load has a known Release path.