# 6. Content Builds Updates and CI Part of [[Addressables]]. Previous: [[5. Scenes Catalogs and Remote Content]]. Next: [[7. Addressables Pitfalls and Quest]]. > [!note] Verification status > Content builds and the update/Prevent Updates workflow are official Addressables features (the 4.x changelog still refers to the content-update restrictions window and Prevent Updates groups, so the concept has continued past 2.9). **Exact Groups-window button labels** can differ between 2.9 and 4.1 and were not click-verified. The CI hook is a command-line `-executeMethod` you add next to [[2. Command Line Builds and a Build Script]]. **Not run in Unity or on GitHub Actions.** ## 6.1 Two builds A player build (Build Profile) produces the executable. An Addressables **content build** produces the bundles plus the catalog in the local / remote build paths from the active Addressables profile. Order that works: 1. Set the Addressables profile (`Local` or `RemoteDev`). 2. Run a **New Build > Default Build Script** from the Addressables Groups / Build menu (wording varies by version). 3. Then build the player (or include the content-build call in the same Editor script, still on one platform — [[2. Command Line Builds and a Build Script]]). If you skip (2), a Player using "existing build" / packed-mode data will have nothing to load. CI that only calls `BuildPipeline.BuildPlayer` will ship an empty catalog. Output of a local profile usually lands under `Library` / `ServerData` / `StreamingAssets` depending on how the profile is set. Whatever is supposed to ship *inside* the player must be in a path the player includes (typically StreamingAssets). Whatever is remote must be **uploaded** to the host (CCD or otherwise) as a second CI step. ## 6.2 Content updates (patches without a new player) The "content update" workflow is how you ship a new hat without resubmitting the whole store build: 1. Some groups are marked so they **should not change** in a patch (binaries already inside the player, or a "Prevent Updates" style constraint — the exact schema name in your version is the one to use). 2. You run the **content update** build, which compares against a previous content state and emits new bundles / a new catalog for what *did* change. 3. The player downloads the new catalog, then only the changed bundles. This is powerful and easy to misuse. Assets in a "static" group that *do* change get pulled into an update group (folder entries have had several official fixes here in 4.x). For a class, demonstrate it once with a single remote texture. For a shipped Quest title, practice on a staging catalog before you point the live load path at it. If you do not need patches, skip this and do a full content build with every player build. That is the honest path for most student projects. ## 6.3 Hooking CI Add a static method that you call **before** `BuildPipeline.BuildPlayer`, in the same Editor process, already started with the right `-activeBuildProfile` / platform: ```csharp #if UNITY_EDITOR using UnityEditor; using UnityEditor.AddressableAssets; using UnityEditor.AddressableAssets.Settings; using UnityEngine; public static class CiAddressables { public static void BuildContent() { AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.Settings; if (settings == null) { Debug.LogError("CiAddressables: no AddressableAssetSettings in the project."); EditorApplication.Exit(1); return; } AddressableAssetSettings.BuildPlayerContent(); Debug.Log("CiAddressables: BuildPlayerContent finished."); } } #endif ``` `AddressableAssetSettings.BuildPlayerContent()` is the common Editor API for a default content build. **Confirm the method and any return/result type against your installed package** (2.9 vs 4.1 may add overloads or a result struct). If the API reports failure in your version, exit non-zero. A cautious CI sequence: 1. `-executeMethod` content build (same platform as the player) 2. `-executeMethod` or `-build` the player 3. If remote: upload the remote build folder to the host (separate step; credentials in secrets) Do not start a second Unity process in between and expect the first process's output to be optional — the player needs the files from step 1. ## 6.4 Localization and other packages [[Localization]] stores tables as Addressable assets. A content build is also a localization build. If a locale is missing in the Player but present in the Editor, the usual cause is a group excluded from the content build or a Play Mode Script that hid the problem. ## Official docs - Addressables 2.9.1 manual index: https://docs.unity3d.com/Packages/[email protected]/manual/index.html - [[Build Automation and CI]]