Unity Addressables: Choose Local or Remote Groups
Split Unity Addressables into local and remote groups to control install size, then verify with the Analyze tool before shipping.
21 Jul 2025, 03:04 UTC

The Problem: Your Initial Download Is Too Large
\nWhen every level, character model, and music track sits in the main build, new players download everything before they can start. On mobile, that means bigger installs, slower launches, and higher uninstall rates. Unity's Addressables system lets you move optional content out of the base install and load it by string address only when needed.
\n\nThe Decision: Local Group or Remote Group
\nOpen the Addressables Groups window (Window > Asset Management > Addressables > Groups). Each group has a Build Path and a Load Path. Set Build Path to LocalBuildPath for content that ships inside the player, and RemoteBuildPath for content fetched from a server after install.
\nUse this as your content budget. Core scenes and the player controller belong in a Local group so the game can start without a network. Cosmetic packs, bonus levels, and localized audio belong in a Remote group. The build step generates catalog files that map each address to a bundle, and those catalogs travel with your build or live on your content host.
\n\nWorked Example: Load a Level Scene on Demand
\nThis example loads a level scene additively and keeps the handle so the scene can be unloaded later. It assumes the Addressables package is installed and the scene is marked addressable with the key \"Level_Forest\".
\nusing UnityEngine;\nusing UnityEngine.AddressableAssets;\nusing UnityEngine.ResourceManagement.AsyncOperations;\nusing UnityEngine.SceneManagement;\n\npublic class LevelLoader : MonoBehaviour\n{\n [SerializeField] private string levelAddress = \"Level_Forest\";\n private AsyncOperationHandle<SceneInstance> loadHandle;\n\n public async void LoadLevel()\n {\n loadHandle = Addressables.LoadSceneAsync(levelAddress, LoadSceneMode.Additive);\n await loadHandle.Task;\n\n if (loadHandle.Status == AsyncOperationStatus.Succeeded)\n {\n Debug.Log(\"Level loaded: \" + levelAddress);\n }\n else\n {\n Debug.LogError(\"Failed to load \" + levelAddress + \": \" + loadHandle.OperationException);\n }\n }\n\n public void UnloadLevel()\n {\n if (loadHandle.IsValid())\n {\n Addressables.UnloadSceneAsync(loadHandle);\n loadHandle = default;\n }\n }\n}\n\nStore the AsyncOperationHandle<SceneInstance> returned by LoadSceneAsync. Passing that same handle to UnloadSceneAsync tells Addressables to release the scene when it is no longer needed. Dropping the handle without unloading leaves native memory allocated, and the C# garbage collector cannot reclaim it.
To test remote delivery locally, run a simple file server from the folder containing your built remote catalog:
\npython3 -m http.server 8000\n\nRun this in a terminal, not inside Unity. Point the Addressables remote load path to http://localhost:8000, build the player, and confirm the level appears from the network URL. Editor play mode can load from local caches, so a built player is the only reliable check. Risks include incorrect MIME types and cache headers on the real host, which a local server will not reveal.
\n\nTrade-Off: Async Complexity and Catalog Versioning
\nAddressables replace direct references with asynchronous lookups. Every load can fail because of a missing key, a dropped connection, or a slow disk, so your code needs null checks and fallback behavior. The build also emits catalog files that must be versioned alongside the player; if the client catalog does not match the hosted bundles, addresses resolve to nothing.
\nThe system does not automatically deduplicate shared assets across bundles. A texture used by both a local character and a remote level can end up in multiple bundles, increasing download size. Run Window > Asset Management > Addressables > Analyze before building to inspect bundle contents and spot duplicates.
\n\nVerification: Check Before You Ship
\n- \n
- Open the Addressables Groups window and confirm every asset has exactly one address and belongs to the intended group. \n
- Run the Addressables Analyze tool and review bundle sizes for duplicated textures or scripts. \n
- Build a standalone player and load the remote address from that build. Do not rely on Editor-only results. \n
- Use the Memory Profiler package to take a snapshot before and after a load/unload cycle; native memory should return near baseline. \n
The Bottom Line
\nAddressables are worth the setup when your base install is growing faster than your content pipeline can manage. Start with one remote group, load a single optional scene with the handle pattern above, and verify with Analyze and a built player. If your project stays small and ships on a single platform, the added build complexity may not pay off yet.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.