Asset Prefetcher
A runtime Addressables memory cache with a configurable byte budget and LRU eviction, prewarmed by label at boot and inspectable live through a runtime Cache Inspector.
What the system is for
Addressables solves how to load an asset by key; it does not solve when to load it or how much memory a project is willing to spend keeping assets around. Without a deliberate cache layer, games either reload the same assets over and over — paying a loading hitch every time — or hold everything in memory indefinitely until a platform's budget runs out.
Serenity's Asset Prefetcher sits between game code and Addressables as a runtime memory cache with a configurable byte budget. Assets are prefetched by key or prewarmed by label at boot, kept in memory up to the budget, and evicted least-recently-used when a new asset would push the cache over it — no code beyond a config asset and a handful of use-case calls.
The Unity problem
Loading an Addressable the first time it is needed is simple but produces a visible hitch right when the player is looking at the screen — a menu opening, a level starting, an enemy archetype appearing for the first time. Prewarming everything up front avoids the hitch but has no natural limit: memory usage grows with the project until something is manually pruned.
Even a hand-written cache tends to skip the hard part — deciding what to evict when the budget is exceeded, and doing it consistently rather than through ad hoc cleanup calls scattered across scene transitions. Without a shared cache, two systems that both want to keep an asset warm end up loading and unloading it past each other.
How Serenity approaches it
A PrefetchPolicyProfile authors the cache's budget and policy — a byte budget, an intended item cap and a named strategy and eviction policy — grouped by a PrefetchPolicyRegistry that resolves profiles by id. IAssetPrefetcherService is the runtime cache: prefetch an asset by key, prewarm a batch, query cache status, and let the service evict least-recently-used entries automatically whenever the byte budget is exceeded.
PrewarmAssetsByLabelsTask runs during boot, resolving a list of Addressables labels to keys and prefetching each one before the player reaches the content that needs it — one task, driven by data, instead of a hand-maintained list of assets to warm scattered through initialization code.
How it fits into Serenity
The enforced policy today is the size budget with LRU eviction: MaxSizeMB is the load-bearing knob, clamped to a floor so a project can never configure the cache down to nothing, and the service evicts the least-recently-used entry whenever a new asset would push total cached bytes past that budget. Strategy and eviction fields on the profile are carried into the runtime for forward compatibility but do not yet change service behavior beyond that.
The service composes with the Initialization Pipeline as a boot-time installer and with PrewarmAssetsByLabelsTask for label-driven warming, and with any aggregate that loads Addressables — characters, waves, audio, UI prefabs — through the same label-based prewarm list, with no per-aggregate coupling to the cache itself.
Practical workflow
- Author a PrefetchPolicyProfile with a byte budget (MaxSizeMB) and add it to a PrefetchPolicyRegistry so it can be resolved by id at boot.
- Wire the registry into the Asset Prefetcher installer as part of your initialization pipeline so the cache exists before gameplay needs it.
- Add PrewarmAssetsByLabelsTask to the boot sequence with the Addressables labels you want warmed before the player reaches that content.
- Call IAssetPrefetcherService.PrefetchAsync for on-demand loads, or PrewarmContextAsync for a batch, from any gameplay system that needs an asset kept warm.
- Open the runtime Cache Inspector on the live service to see per-asset cache contents grouped by category — Animations, Audio, Textures — alongside cache diagnostics.
- Use the Cache Inspector's Refresh and Clear actions during development to confirm the budget and eviction behavior before shipping the profile's numbers.
What you get
- IAssetPrefetcherService runtime cache with prefetch-by-key, batch prewarm and cache-status queries
- PrefetchPolicyProfile and PrefetchPolicyRegistry ScriptableObjects authoring a named byte budget and policy
- Configurable byte budget with automatic LRU eviction whenever cached bytes exceed the budget
- PrewarmAssetsByLabelsTask for boot-time prewarm of every asset carrying a chosen Addressables label
- Live Cache Inspector on the runtime service — per-asset contents grouped by category (Animations, Audio, Textures)
- Cache diagnostics and Refresh/Clear controls in the inspector for fast iteration during development
- Composes with any Addressables-loading aggregate through label-based prewarm, with no per-aggregate coupling
- Honest scope: the enforced policy today is the size budget with LRU eviction, ahead of any future strategy support
When to use this
- Projects that see loading hitches from Addressables assets being loaded for the first time right when the player is looking at the screen.
- Games that want a memory ceiling on cached assets instead of either reloading constantly or holding everything indefinitely.
- Teams that want boot-time prewarm driven by Addressables labels rather than a hand-maintained list of assets to warm in code.
- Codebases that need visibility into what is currently cached and why something was evicted, without reflection-diving into Addressables internals.
Related systems
Use Serenity when you want Addressables assets kept warm under a real memory budget, evicted automatically when that budget is exceeded, and visible at a glance through a live Cache Inspector.
English
Español
Català