Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Discussion TIL: Creating AssetBundles from the command line

Discussion in 'Scripting' started by WallaceT_MFM, Mar 31, 2023.

  1. WallaceT_MFM


    Sep 25, 2017
    I saw a few post of people asking about building asset bundles from the command line with Unity. I needed to do this because I have a large number of Unity project that reference each other's scripts through the package manager, but the assets (scenes, prefabs, etc) are not included in the packages. So, if I want to rebuild all of the asset bundles for every project, I have to open each project and build bundles there. I have about 20 project like this, so this get very tedious. I also can't use an editor script alone to do this because the assets (and their metadata) are in different projects.

    Fortunately, Unity has a cli batch mode, which allows us to run Unity from the command line and do some basic things.
    In particular, using -projectPath, -batchmode, and -executeMethod lets me launch Unity from the command line and execute a method of my choice. In turn, I can create a new class and method specifically for building asset bundles.

    Code (CSharp):
    1. public class AssetBundlesBuilder
    2. {
    3.     public static void BuildBundles()
    4.     {
    5.         string[] args = Environment.GetCommandLineArgs();
    6.         string path = "";
    7.         string target = "";
    8.         for (int i = 0; i < args.Length; i++)
    9.         {
    10.             if(args[i] == "-path")
    11.             {
    12.                 path = args[i + 1];
    13.             }
    14.             if(args[i] == "-target")
    15.             {
    16.                 target = args[i + 1];
    17.             }
    18.         }
    19.         path += "/assetbundles";
    20.         Directory.CreateDirectory(path + "/windows");
    21.         Directory.CreateDirectory(path + "/android");
    22.         Directory.CreateDirectory(path + "/ios");
    24.         if (target == "all" || target == "")
    25.         {
    26.             BuildPipeline.BuildAssetBundles(path + "/windows", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
    27.             BuildPipeline.BuildAssetBundles(path + "/android", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.Android);
    28.             BuildPipeline.BuildAssetBundles(path + "/ios", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.iOS);
    29.         }
    30.         else if (target == "windows")
    31.         {
    32.             BuildPipeline.BuildAssetBundles(path + "/windows", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
    33.         }
    34.         else if (target == "android")
    35.         {
    36.             BuildPipeline.BuildAssetBundles(path + "/android", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.Android);
    37.         }
    38.         else if (target == "ios")
    39.         {
    40.             BuildPipeline.BuildAssetBundles(path + "/ios", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.iOS);
    41.         }
    42.         else
    43.         {
    44.             throw new Exception("Invalid Build Target");
    45.         }
    47.         if (Application.isBatchMode)
    48.         {
    49.             EditorApplication.Exit(0);
    50.         }
    51.     }
    52. }
    This is the code for building asset bundles for the 3 platforms I support. It needs to exist in an Editor folder in each project that needs to build bundles. I use chunk-based compression, but that isn't required in general. The code above looks for a couple command line arguments: -path and -target. -path specifies an output path for the finished bundles. -target is expected to be one of "windows", "android", "ios", or "all" and determines which platform to build for. If -target isn't supplied, it will default to building bundles for all platforms.

    To get bundles from the command line, I call it like so:
    "<path-to-unity>Unity.exe" -projectPath "<path>" -batchmode -executeMethod AssetBundlesBuilder.BuildBundles -path "<outputPath>" -target all

    That line, combined with the AssetBundlesBuilder, makes all of the bundles for 1 project.
    -nographics seemed to make this not work, and I don't know why. I'm guessing that the building process needs graphics for building shaders and such, not sure. Likewise, including -quit did not seem to be needed. Not including both of those works fine.

    Now I said I have about 20 projects that need this done, and at this point we've solved it for one project. All of my projects are fortunately located in the same folder, like so
    Code (CSharp):
    1. ParentFolder
    2. --Project1Root
    3. ----Assets
    4. ----...
    5. --Project2Root
    6. ----Assets
    7. ----...
    8. --...
    So, a little batch script later and now I can build all bundles for all project, automatically, without the worry that I might lose track of where I was or accidentally skip over a project, or just one project for one platform.

    Here's the batch file:
    Code (CSharp):
    1. @echo off
    3. echo "Building bundles to %cd%\Bundles"
    4. for /d %%i in (*) do (
    5.   if exist "%%i\Assets" (
    6.     echo %%~dpni
    7.     start "" /wait "C:\Program Files\Unity\Hub\Editor\2021.3.19f1\Editor\Unity.exe" -projectPath "%%~dpni" -batchmode -executeMethod AssetBundlesBuilder.BuildBundles -path "%cd%\Bundles"
    8.   )
    9. )
    11. pause
    cmd uses some truly arcane syntax, but I was able to piece that together. This batch file is placed in the parent folder, beside the root folders for the projects. The script only builds the bundles one project at a time because starting 20 instances of Unity at the same time and telling them all to build bundles simultaneously would make my computer very sad.

    Hope someone finds this useful. Thank you for coming to my Ted Talk.
  2. liortal


    Oct 17, 2012
    @WallaceT_MFM in case you need to call methods that take in arguments (instead of reading them yourself), check out my (free) GitHub project UCmd.

    Also, available on the asset store.