简体   繁体   中英

Unity: How to build AssetBundles into separate directories per AssetBundle

My project contains multiple AssetBundles, and I want to be able to click a button in the Editor which builds all AssetBundles out into their own appropriately named folders .

In other words, given AssetBundles named "A" and "B", the out put would be two folders where "A" contains the built bundled assets which were labelled for inclusion in "A", and likewise a similar folder for "B".

I have familiarised myself to some degree with the AssetBundleBuild and BuildPipeline classes.

This led me to produce the following script (see below).

I feel I am quite close in that I have got a list of all the asset bundles in the project, set up directories for them, and tried to build them. The issue is that I am getting the following error:

Manifest AssetBundle name "example_bundle_name" has conflict with the user predefined AssetBundle name.

What do I need to do to make this work, please?

public class BuildAssetBundles : MonoBehaviour
{
    private const string AssetBundleRootDirectory = "Assets/BuiltAssetBundles";
    private const BuildTarget BuildTarget = UnityEditor.BuildTarget.StandaloneWindows;

    [MenuItem("Build Asset Bundles/Build All Asset Bundles")]
    public static void BuildBundlesIntoDirectories()
    {
        Debug.Log("Asset bundle building started...");
        // Get all assets

        var assets = AssetDatabase.GetAllAssetPaths().ToArray();

        List<AssetBundleBuild> assetBundleBuilds = new List<AssetBundleBuild>();
        HashSet<string> processedBundles = new HashSet<string>();

        // Get asset bundle names from selection
        foreach (var o in assets)
        {
            var assetPath = o;
            var importer = AssetImporter.GetAtPath(assetPath);

            if (importer == null)
            {
                continue;
            }

            // Get asset bundle name & variant
            var assetBundleName = importer.assetBundleName;
            var assetBundleVariant = importer.assetBundleVariant;
            var assetBundleFullName = string.IsNullOrEmpty(assetBundleVariant) ? assetBundleName : assetBundleName + "." + assetBundleVariant;

            // Only process assetBundleFullName once. No need to add it again.
            if (processedBundles.Contains(assetBundleFullName))
            {
                continue;
            }

            processedBundles.Add(assetBundleFullName);

            AssetBundleBuild build = new AssetBundleBuild();

            build.assetBundleName = assetBundleName;
            build.assetBundleVariant = assetBundleVariant;
            build.assetNames = AssetDatabase.GetAssetPathsFromAssetBundle(assetBundleFullName);

            assetBundleBuilds.Add(build);
        }

        foreach (var assetBundle in assetBundleBuilds.ToArray())
        {
            if(!String.IsNullOrWhiteSpace(assetBundle.assetBundleName))
                BuildAnAssetBundle(assetBundle);
        }
        Debug.Log("Asset bundle building finished.");

    }

    static void BuildAnAssetBundle(AssetBundleBuild assetBundleToBuild)
    {
        // Put the bundles in a folder within the Assets directory.
        string assetBundleOutputDirectory = Path.Combine(AssetBundleRootDirectory, assetBundleToBuild.assetBundleName);
        if (string.IsNullOrWhiteSpace(assetBundleToBuild.assetBundleVariant))
        {
            Path.Combine(assetBundleOutputDirectory, assetBundleToBuild.assetBundleVariant);
        }

        if(!Directory.Exists(assetBundleOutputDirectory))
            Directory.CreateDirectory(assetBundleOutputDirectory);


        try
        {
            BuildPipeline.BuildAssetBundles(assetBundleOutputDirectory, new AssetBundleBuild[]{assetBundleToBuild}, BuildAssetBundleOptions.None, BuildTarget);
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }
    }
}

Many thanks in advance for your help and suggestions.

The error seems to imply to me that my approach is slightly incorrect, maybe in setting up the AssetBundleBuild it is making a duplicate asset bundle containing all the contents of the original with an identical name.

Why are you writing code to build AssetsBundle? Is there anything AssetBundle Browser can not do? Just download it Asset Store or Github and organize your bundles as you wish.

I have solved this problem by writing a separate method to organise the assetbundle files once they have been built.

This works by taking the name of the assetbundle files (minus the extension) and creating a directory of the same name (if one does not already exist). Having created all directories, I then move the files of the same names into the relevant directory.

Note: On Windows (at least), you will have two files, the bundle itself and the manifest. The manifest has an extension but the bundle file does not. I am giving the file a temporary file extension so that I can create a directory of the same name, in the same directory that the extension-less bundle file resides, before reverting after moving.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM