SoFunction
Updated on 2025-03-07

Detailed explanation of Unity AssetBundle Packaging Tool Example

Unity batch AB package

For resource hot updates, Unity supports packaging all resources into AssetBundle resources and storing them in the SteamingAssets folder;

Before the project is released, all resources need to be packaged into .ab files and loaded dynamically;

When the project is updated, replace the .ab resource file to complete the hot update;

When ab files are loaded, there will be an extra process of decompression, which will increase performance consumption;

Packaging operations are editor expansion, and all scripts are placed in the Eidtor folder;

Obtain ab output and input path according to different platforms;

The input and output paths of different platforms are different, ios, android, and windows;"Introduction to Unity Resource Folder"

public class PathTools
{
    // Package the AB package root path    public const string AB_RESOURCES = "StreamingAssets"; 
    
    // Get the input directory of AB resources    public static string GetABResourcesPath()
    {
        return  + "/" + AB_RESOURCES;
    }

    // Obtain the AB packet output path    public static string GetABOutPath()
    {
        return GetPlatformPath() + "/" + GetPlatformName();
    }
    
    //Get the platform path    private static string GetPlatformPath()
    {
        string strReturenPlatformPath = ;

#if UNITY_STANDALONE_WIN
        strReturenPlatformPath = ;
#elif UNITY_IPHONE
            strReturenPlatformPath = ;
#elif UNITY_ANDROID
            strReturenPlatformPath = ;
#endif
        
        return strReturenPlatformPath;
    }
    
    // Get the platform name    public static string GetPlatformName()
    {
        string strReturenPlatformName = ;

#if UNITY_STANDALONE_WIN
        strReturenPlatformName = "Windows";
#elif UNITY_IPHONE
            strReturenPlatformName = "IPhone";
#elif UNITY_ANDROID
            strReturenPlatformName = "Android";
#endif

        return strReturenPlatformName;
    }
    
    // Return to WWW Download AB package loading path    public static string GetWWWAssetBundlePath()
    {
        string strReturnWWWPath = ;

#if UNITY_STANDALONE_WIN
        strReturnWWWPath = "file://" + GetABOutPath();
#elif UNITY_IPHONE
            strReturnWWWPath = GetABOutPath() + "/Raw/";
#elif UNITY_ANDROID
            strReturnWWWPath = "jar:file://" + GetABOutPath();
#endif

        return strReturnWWWPath;
    }
}

Function: Select a folder and package all resource files in the folder into AB files;

Main logic: traversing all files in the folder is the generation of the file. AssetBundleBuild is packaged in a unified manner in the linked list. It is the recursive previous operation of the folder, and put all resource files in the listassets linked list;

Official API: Unified package of all resources;

public class CreateAB : MonoBehaviour
{
    private static string abOutPath;
    private static List<AssetBundleBuild> listassets = new List<AssetBundleBuild>();
    private static List<DirectoryInfo> listfileinfo = new List<DirectoryInfo>();
    private static bool isover = false; // Whether the check is completed, you can pack it    static private string selectPath;

    public static bool GetState()
    {
        return isover;
    }

    public static AssetBundleBuild[] GetAssetBundleBuilds()
    {
        return ();
    }

    [MenuItem("ABTools/CreatAB &_Q", false)]
    public static void CreateModelAB()
    {
        abOutPath = ;

        if (!(abOutPath))
            (abOutPath);

         obj = ;
        selectPath = (obj);
        SearchFileAssetBundleBuild(selectPath);
        
        (abOutPath,
            (), , );
        ("AssetBundle is packaged");
    }

    [MenuItem("ABTools/CreatAB &_Q", true)]
    public static bool CanCreatAB()
    {
        if ( > 0)
        {
            return true;
        }
        else
            return false;
    }

I don't know why it's popular here...

//It's a file, continue to go down    public static void SearchFileAssetBundleBuild(string path) 
    {
        DirectoryInfo directory = new DirectoryInfo(@path);
        FileSystemInfo[] fileSystemInfos = ();
        ();
        //Transfuse all files in all folders        foreach (var item in fileSystemInfos)
        {
            int idx = ().LastIndexOf(@"\");
            string name = ().Substring(idx + 1);
            //item is a folder, add it to listfileinfo, and call it recursively            if ((item as DirectoryInfo) != null)
                (item as DirectoryInfo);
            
            //Exclude meta files, create AssetBundleBuild for other files and add them to listassets;            if (!(".meta"))
            {
                CheckFileOrDirectoryReturnBundleName(item, path + "/" + name);
            }
        }

        if ( == 0)
            isover = true;
        else
        {
            ();
        }
    }

    //Judge whether it is a file or a folder    public static string CheckFileOrDirectoryReturnBundleName(FileSystemInfo fileSystemInfo, string path) 
    {
        FileInfo fileInfo = fileSystemInfo as FileInfo;
        if (fileInfo != null)
        {
            string[] strs = ('.');
            string[] dictors = strs[0].Split('/');
            string name = "";
            for (int i = 1; i < ; i++)
            {
                if (i <  - 1)
                {
                    name += dictors[i] + "/";
                }
                else
                {
                    name += dictors[i];
                }
            }

            string[] strName = ('/');
            AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
             = strName[ - 1];
             = "ab";
             = new string[] {path};
            (assetBundleBuild);
            return name;
        }
        else
        {
            //Recursive call            SearchFileAssetBundleBuild(path);
            return null;
        }
    }
}

When packaging, a tag will be added to each resource. If packaged repeatedly, it needs to be cleared before packaging can be packaged again, otherwise it will fail;

Use the official API:();

Because the comments are written in detail, I won’t go into details;

public class ClearABLable
{
    [MenuItem("ABTools/Remove AB Label")]
    public static void RemoveABLabel()
    {
        // The root directory of the tag needs to be removed        string strNeedRemoveLabelRoot = ;
        // Directory information (scene directory information array, representing all scene directories under the root directory)        DirectoryInfo[] directoryDIRArray = null;
        
        // Define the folder root directory of the resource that needs to be removed from the AB tag        strNeedRemoveLabelRoot = ();   

        DirectoryInfo dirTempInfo = new DirectoryInfo(strNeedRemoveLabelRoot);
        directoryDIRArray = ();

        //Travel through all directories or files in this scene directory        foreach (DirectoryInfo currentDir in directoryDIRArray)
        {
            // Recursively call the method and find the file, use the AssetImporter class to mark "package name" and "suffix name"            JudgeDirOrFileByRecursive(currentDir);
        }

        // Clear useless AB markers        ();
        // refresh        ();

        // Prompt message, mark the package name to complete        ("AssetBundle This operation removes the mark completed");
    }

    /// <summary>
    /// Recursively determine whether it is a directory or file    /// is a file, modify the Asset Bundle tag    /// It is a directory, then continue to recurse    /// </summary>
    /// <param name="fileSystemInfo">Current file information (file information and directory information can be converted to each other)</param>    private static void JudgeDirOrFileByRecursive(FileSystemInfo fileSystemInfo)
    {
        // Parameter check        if ( == false)
        {
            ("File or directory name:" + fileSystemInfo + "Not exist, please check");
            return;
        }

        // Get the file information collection at the next level of the current directory        DirectoryInfo directoryInfoObj = fileSystemInfo as DirectoryInfo; 
        // Convert file information to directory information        FileSystemInfo[] fileSystemInfoArray = ();

        foreach (FileSystemInfo fileInfo in fileSystemInfoArray)
        {
            FileInfo fileInfoObj = fileInfo as FileInfo;

            // File Type            if (fileInfoObj != null)
            {
                // Modify the AssetBundle tag of this file                RemoveFileABLabel(fileInfoObj);
            }
            // Directory type            else
            {
                // If it is a directory, then call it recursively                JudgeDirOrFileByRecursive(fileInfo);
            }
        }
    }

    /// &lt;summary&gt;
    /// Remove Asset Bundle tags to the file    /// &lt;/summary&gt;
    /// <param name="fileInfoObj">File (file information)</param>    static void RemoveFileABLabel(FileInfo fileInfoObj)
    {
        // AssetBundle package name        string strABName = ;
        // File path (relative path)        string strAssetFilePath = ;

        // Parameter check (*.meta file is not processed)        if ( == ".meta")
        {
            return;
        }

        // Get the AB package name        strABName = ;
        // Get the relative path to the resource file        int tmpIndex = ("Assets");
        // Get the file relative path        strAssetFilePath = (tmpIndex); 
        
        // Remove AB name to the resource file        AssetImporter tmpImportObj = (strAssetFilePath);
         = strABName;
    }
}

4. Expand

More often, we need to package one click, or we may need to type multiple files into an AB package, and we only need to modify the file logic;

The ab package itself is not complicated, and it processes file path strings more frequently, and debugs more often;

This is all about this article about the Unity AssetBundle packaging tool. For more information about Unity AssetBundle packaging, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!