Rebuilding only changed assets

We do custom processing in addressable builds, something like:

protected override string ProcessGroup(AddressableAssetGroup assetGroup, AddressableAssetsBuildContext aaContext)
{
    try
    {
        if (assetGroup.HasSchema<BundledAssetGroupSchema>() && assetGroup.GetSchema<BundledAssetGroupSchema>().IncludeInBuild)
        {
            var platformSchema = assetGroup.HasSchema<FilterAddressablesSchema>() ? assetGroup.GetSchema<FilterAddressablesSchema>() : null;
            if (platformSchema && !platformSchema.Matches(m_Target))
            {
                m_ReEnable.Add(assetGroup);
                assetGroup.GetSchema<BundledAssetGroupSchema>().IncludeInBuild = false;
                Debug.Log($"Skipped asset group: {assetGroup.Name}");
                return "";
            }
            foreach (var entry in assetGroup.entries.ToList()) // Make it a list such that we get a new collection, otherwise we can't add / remove to entries
            {
                if (entry.IsScene)
                {
                    Debug.Log($"Begin scene: {entry.AssetPath}");
                    var newScene = entry.AssetPath.Replace("Assets/", "Assets/Generated/");
                    System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(newScene));
                    AssetDatabase.CopyAsset(entry.AssetPath, newScene);
                    BuildManager.CompileScene(newScene, m_Target);
                    var newGUID = AssetDatabase.AssetPathToGUID(newScene);
                    var newAsset = aaContext.Settings.CreateOrMoveEntry(newGUID, assetGroup);
                    AssignAssetEntry(newAsset, entry);
                    assetGroup.RemoveAssetEntry(entry);
                    m_RestoreScenes.Add(Tuple.Create(assetGroup, entry, newAsset));
                    Debug.Log($"Fixed scene: {entry.AssetPath}");
                }
            }
        }
    }
    catch (System.Exception e)
    {
        Debug.LogError($"Exception thrown during asset build: {e.Message}\n trace: {e.StackTrace}");
    }
    return base.ProcessGroup(assetGroup, aaContext);
}

In a BuildScriptPackedMode. CompileScene in this case does processing on the scene to be able to have build matrix specific overrides. To do a full game build this takes about 3 & ½ hours on my machine, add in another ~20 minutes to actually build the player and we’re looking at around 4 hours. Now imagine I run this build on the target platform & realize that there’s some kind of bug which is data related & suddenly I have to fix that, and then rebuild everything for another 4 hour turn around time, yet only a very small subset of the assets have actually changed. Perhaps I’m going about this the wrong way from the get go?

Building addressables is agony. I’d love to know what the solution is.

I have been agony by Addressables too. It’s better to use Resources or AssetBundle.

Yeah we’ve found no good solution to this, the API is pretty crap overall & it seems like Addressables are added to a long list of already abandoned projects in Unity. I wouldn’t be surprised if we get a new data delivery format in the future, 4th time the charm perhaps.

I read your codes again, I think you can speed up if not use Linq in foreach.

Rather than this

foreach (var entry in assetGroup.entries.ToList())

Use this instead

var entires = assetGroup.entries.ToList()
foreach (var entry in entires)

Also you can use AssetDatabase.StartAssetEditing() and AssetDatabase.StopAssetEditing(). Your code overall would like this.

            AssetDatabase.StartAssetEditing()
            var entires = assetGroup.entries.ToList()
            foreach (var entry in entires) // Make it a list such that we get a new collection, otherwise we can't add / remove to entries
            {
                if (entry.IsScene)
                {
                    Debug.Log($"Begin scene: {entry.AssetPath}");
                    var newScene = entry.AssetPath.Replace("Assets/", "Assets/Generated/");
                    System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(newScene));
                    AssetDatabase.CopyAsset(entry.AssetPath, newScene);
                    BuildManager.CompileScene(newScene, m_Target);
                    var newGUID = AssetDatabase.AssetPathToGUID(newScene);
                    var newAsset = aaContext.Settings.CreateOrMoveEntry(newGUID, assetGroup);
                    AssignAssetEntry(newAsset, entry);
                    assetGroup.RemoveAssetEntry(entry);
                    m_RestoreScenes.Add(Tuple.Create(assetGroup, entry, newAsset));
                    Debug.Log($"Fixed scene: {entry.AssetPath}");
                }
            }
            AssetDatabase.StopAssetEditing()

Let me know if it speed up building process.