Search Unity

Command Line building of Addressable Assets

Discussion in 'Addressables' started by CyberAngel, Mar 27, 2022.

  1. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
    My current script builds a game, but with Addressable Assets I have an issue.

    To describe what I have, is there are scenes that are added to the system and they have special Editor Scripts that generate Content when the game is built. All works great without Addressable Assets.

    The problem is that these scripts run on the PreProcessBuild, and the Addressables are already built by this stage. So the question is, how can I hook into running specific code for an Addressable Scene, before it is packed up into the build?
     
  2. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    IProcessSceneWithReport - runs every time scene is built. Also run on play mode when scene is being loaded.

    Another option is to extend BuildScriptPackedMode and add hooks yourself. I did exactly that, so now I have
    IPreprocessAddressableBuild that I can implement and it will be called just before addressable build.

    Third option is to just do call necessary code from a script that executes your build.
     
  3. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
    Can I ask which version of Unity you are using? I noticed that in Unity 2019, what I want to do is not possible, but it kind of works in Unity 2020. But in Unity 2021, it doesn't work this way again.
     
  4. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    All of the options I mentioned should work fine in all 3 versions you mentioned. Could you elaborate what exactly did not work in 2019 and 2021?
     
  5. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
    I may need to look into this a bit more then, because from my tests, it didn't work.

    I will give a scenario.

    To keep the scene size down, there is a few generation scripts that are run when the scene is loaded, and these objects are then removed when the scene is unloaded. In Unity 2019, when running a build script from the command line, this won't work as the script that does the generation is never called. In Unity 2020, this script can be called. And in Unity 2021, it is no longer called again.

    And why I am here,

    EDIT: And yes the scenes are marked as Addressables.
     
  6. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    Could you give a minimal code sample of things that work depending on Unity version? Because we use several types of scene processing in production and it always worked fine. Project started with Unity 2019.2, now on 2020.3.
     
  7. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
    There are two scripts, the build script which is

    Code (CSharp):
    1.  
    2. public class BuildScript
    3. {
    4.         static bool mIsListening = false;
    5.         static public void TrustyBuild()
    6.         {
    7.             BuildAddressables();
    8.         }
    9.         public static void BuildAddressables(object o = null)
    10.         {
    11.             if (EditorApplication.isCompiling)
    12.             {
    13.                 if (false == mIsListening)
    14.                 {
    15.                     CompilationPipeline.compilationFinished += BuildAddressables;
    16.                 }
    17.                 mIsListening = true;
    18.                 return;
    19.             }
    20.             if (true == mIsListening)
    21.             {
    22.                 CompilationPipeline.compilationFinished -= BuildAddressables;
    23.             }
    24.             AddressableAssetSettings.CleanPlayerContent();
    25.             AddressableAssetSettings.BuildPlayerContent();
    26.         }
    27.     }
    28.  
    29.  
    The major problem in the code above, is that it doesn't do addressables, it does in Unity 2020, but not Unity 2019 or Unity 2021.

    What the above code is supposed to do is fire the following script.

    Code (CSharp):
    1.  
    2. #if UNITY_EDITOR
    3. public class ObjectRandomizer : MonoBehaviour, IPreprocessBuildWithReport
    4. {
    5.     public int callbackOrder { get { return 0; } }
    6.     public void OnPreprocessBuild(BuildReport report)
    7.     {  
    8.         //This is not getting called when Addressable Assets are being built.
    9.         GeneratePlacement();
    10.     }
    11. }
    12. #endif //UNITY_EDITOR
     
  8. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
  9. manuelgoellnitz

    manuelgoellnitz

    Joined:
    Feb 15, 2017
    Posts:
    397
    I also tried to create a addressable-build script, and in the documentation there is an example how to do it.
    But...
    It only shows how to create a new build, not how to update a previous build.

    So i digged into the sourcecode to reverse engineer how that could be done and I found it.
    But...
    It does not work from outside the package since the part where you set the previous builds data is "internal" (again...)

    Code (CSharp):
    1. ...
    2. var context = new AddressablesDataBuilderInput(settings, cacheData.playerVersion);
    3. context.PreviousContentState = cacheData; //this breaks because the set is internal
    4.  
    5. var result = settings.ActivePlayerDataBuilder.BuildData<AddressablesPlayerBuildResult>(context);
    is there another way to update a previous addressable build, that does not require modifiing the addressables package?
     
  10. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    Hi @CyberAngel I think what's confusing here is that building Addressables is a separate process from building the game/player. IPreprocessBuildWithReport only fires when building the player, not after an Addressables build.

    In 2021.2+ however it's possible to automatically build Addressables during the player build. In Addressables Build settings, set the "Build Addressables on Player Build" to "Build Addressables content on Player Build". Then I would modify your ObjectRandomizer class to use the new BuildPlayerProcessor interface. For more information you can take a look at the AddressablesPlayerBuildProcessor.cs file.

    Otherwise I would follow the advice mentioned earlier to extend the BuildScriptPackedMode class. The BuildDataImplementation method would be overriden like so:
    Code (CSharp):
    1. protected override TResult BuildDataImplementation<TResult>(AddressablesDataBuilderInput builderInput)
    2. {
    3. GeneratePlacement(); // build custom content
    4. base.BuildDataImplementation<TResult>(builderInput); // build addressables
    5. }
    @manuelgoellnitz The setter for PreviousContentState has been made public in 1.20 :). I would follow the same advice as above. You would need to create a custom class that extends BuildScriptPackedMode. Override BuildDataImplementation to modify the AddressablesDataBuilderInput that is passed in.
     
  11. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
    This is all new to me, I would really appreciate a working sample that I could just run with. Also your first link is broken.

    In my work flow I have a build bat file, that builds the game for various platforms, so I require a way to build these addressables from that. This is where I am completely stuck, I just don't understand what I need to do. It also needs to work on Unity 2019, 2020, 2021
     
    Last edited: May 7, 2022
  12. manuelgoellnitz

    manuelgoellnitz

    Joined:
    Feb 15, 2017
    Posts:
    397
    Is that possible now?
    I tried that some month ago and failed because of other "internal" stuff that were not available but necessary in my custom class.
     
    Last edited: May 9, 2022
  13. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    Yep it's been made public in Addressables 1.20.0
     
    manuelgoellnitz likes this.
  14. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    Hmm yeah for older versions I think you will need build Addresables separately before building the player. So what you'd want to do is create a custom Addressables build script and set that as the active build script. Then you can build Addressables, and if that succeeds go ahead and build the player. We have a few pages in the docs that explains how to do this:

    https://docs.unity3d.com/Packages/com.unity.addressables@1.20/manual/ContinuousIntegration.html

    https://docs.unity3d.com/Packages/com.unity.addressables@1.20/manual/BuildPlayerContent.html

    Also there is a sample custom build script that you can download through the package manager. If you open the Addresables page in the package manager, there should be an option to download the "Custom Build and Playmode Scripts" folder.
    https://docs.unity3d.com/Packages/c....20/manual/CustomBuildAndPlaymodeScripts.html
     
  15. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
    I have tried these with very little success, in fact one of these attempts built the scene with no lights.
     
  16. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    Hmm I see, then I would suggest trying IProcessSceneWithReport or PostProcessSceneAttribute again. These will only work for modifying scenes, not prefabs. I think PostProcessSceneAttribute is newer API, so that might work better for newer Unity versions.

    https://docs.unity3d.com/ScriptReference/Callbacks.PostProcessSceneAttribute.html
     
  17. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
    Same result with that, the Addressable scene has no assets generated!
     
  18. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    Hmm I see, could you explain how the objects should be generated in the scene? Are they being randomly generated?
     
  19. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
    That is correct they are being randomly generated, the reason for this is that when the scene is loaded it uses a seed value to randomly generate trees, fences, flowers and many non interactive objects. This is to keep the scene size to an absolute minimum size for Github.

    The issue is that I am trying to load the scene and generate these objects before the Addressable is built. In some of the examples that I tried, I get no generated objects, and I get no lighting on the scene either. For example I have a main scene that controls certain things, and then additively load a scene that is the main game. Once that happens when built all addressable have no lighting
     
  20. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    Thanks for the explanation! The problem with this approach is that the empty scenes are being cached to the build pipeline (aka the BuildCache API https://docs.unity3d.com/Packages/c...itor.Build.Pipeline.Utilities.BuildCache.html). To achieve the behavior that you want, you would need to clear the build pipeline cache each time before running a build (not recommended) or create an editor script that would generate objects before the build.
     
  21. CyberAngel

    CyberAngel

    Joined:
    Oct 4, 2014
    Posts:
    128
    And the last option is not going to work if they are Addressables!